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)]; // 选择一个pivot int leftEnd = partition(array, left, right, pivot); // returns end of left partition int leftSize = leftEnd - left + 1; // 左半边比pivot小的数 if (leftSize == requiredCount + 1) { // 满足条件 return max(array, left, leftEnd); } else if (requiredCount < leftSize) { // leftSize多了,在leftSize区间中partition return rank(array, left, leftEnd, requiredCount); } else { // leftSize小了,在leftEnd右侧继续partition return 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."); } }