Hard 找最小的k个数(Selection Rank) @CareerCup

来源:互联网 发布:java api 1.8中文 编辑:程序博客网 时间:2024/06/06 00:13

1 排序 O(nlogn)

2 建最大堆,插入新元素的同时,不断删除最大元素O(nlogk)

3 Selection Rank 算法,注意partition方法,极其容易写错!我会另外写一篇专门讲这个算法!

更新:已经写了:http://blog.csdn.net/fightforyourdream/article/details/21373279


package Hard;import java.util.Arrays;import CtCILibrary.AssortedMethods;/** * Describe an algorithm to find the smallest 1 million numbers in 1 billion numbers. Assume that the computer memory can hold all one billion numbers.译文:描述一个算法,在10亿个数中找到最小的1百万个数。假设内存可以一次性装入这10亿个数。 * */public class S18_6 {class Parts {public int left;public int right;public Parts(int l, int r) {left = l;right = r;}}// 直接排序后取前requiredCount个元素public static int rankB(int[] array, int requiredCount) {int[] cloned = array.clone();Arrays.sort(cloned);return cloned[requiredCount];}public static void swap(int[] array, int i, int j) {int t = array[i];array[i] = array[j];array[j] = t;}public static boolean validate(int[] array, int left, int right, int pivot,int endLeft) {for (int i = left; i <= endLeft; i++) {if (array[i] > pivot) {return false;}}for (int i = endLeft + 1; i <= right; i++) {if (array[i] <= pivot) {return false;}}return true;}public static boolean validateFull(int[] array) {for (int i = 0; i < array.length; i++) {for (int j = i; j < array.length; j++) {for (int k = i; k <= j; k++) {int[] cloned = array.clone();int pivot = array[k];int p = partition(cloned, i, j, pivot);if (!validate(cloned, i, j, pivot, p)) {AssortedMethods.printIntArray(cloned);String val = p >= 0 && p < cloned.length ? String.valueOf(array[i]) : "?";System.out.println("pivot: " + pivot + " | " + p+ " | " + val);return false;}}}}return true;}public static boolean isUnique(int[] array) {int[] cloned = array.clone();Arrays.sort(cloned);for (int i = 1; i < cloned.length; i++) {if (cloned[i] == cloned[i - 1]) {return false;}}return true;}public static int max(int[] array, int left, int right) {int max = Integer.MIN_VALUE;for (int i = left; i <= right; i++) {max = Math.max(array[i], max);}return max;}public static int randomInt(int n) {return (int) (Math.random() * n);}public static int randomIntInRange(int min, int max) {return randomInt(max + 1 - min) + min;}// 调整array使得pivot左边都是比pivot小的,pivot右边都是比pivot大的public static int partition(int[] array, int left, int right, int pivot) {while (true) {while (left <= right && array[left] <= pivot) {left++;}while (left <= right && array[right] > pivot) {right--;}if (left > right) {return left - 1;}swap(array, left, right);}}// 容易写错!! O(n)public static int rank(int[] array, int left, int right, int requiredCount) {int pivot = array[randomIntInRange(left, right)];// 选择一个pivotint leftEnd = partition(array, left, right, pivot); // returns end of left partitionint leftSize = leftEnd - left + 1;// 左半边比pivot小的数if (leftSize == requiredCount + 1) {// 满足条件return max(array, left, leftEnd);} else if (requiredCount < leftSize) {// leftSize多了,在leftSize区间中partitionreturn rank(array, left, leftEnd, requiredCount);} else {// leftSize小了,在leftEnd右侧继续partitionreturn rank(array, leftEnd + 1, right, requiredCount - leftSize);}}public static void main(String[] args) {int numberOfTests = 1000;int count = 0;while (count < numberOfTests) {// 建一个包含10个范围在[-1000,1000]的随机数的数组int[] array = AssortedMethods.randomArray(10, -1000, 1000);if (isUnique(array)) {int requiredCount = AssortedMethods.randomIntInRange(0, array.length - 1);// 按照递增排序,选择前n个数int rank1 = rank(array.clone(), 0, array.length - 1, requiredCount);int rank2 = rankB(array.clone(), requiredCount);if (rank1 != rank2) {System.out.println("ERROR: " + rank1 + " " + rank2);AssortedMethods.printIntArray(array);}count++;}}System.out.println("Completed " + count + " runs.");}}





0 0
原创粉丝点击