標籤:style blog color io os java ar div art
在一個由n個元素組成的集合中,第i個“順序統計量(order statistic)”是該集合中第i小的元素。例如,在一個由n個元素組成的集合中,最小值是第1個順序統計量,最大值是第n個順序統計量。而“中位元(median)”總是出現在low((n+1)/2)或者high((n+1)/2)處,其中low是向下取整(“下中位元”),high是向上取整(“上中位元”),當n為奇數的時候,只有“下中位元”,而n為偶數的時候,同時有“下中位元”和“上中位元”。
選擇問題的定義如下。
輸入:一個包含n個不同的數的集合A和一個數i,i屬於範圍[1,n]
輸出:集合A中的一個元素x,x恰好大於A中的其他i-1個元素
通過排序的方法可以解決這個問題,比如堆排序、歸併排序。時間可以達到O(n*lg(n))
下面討論一個實用的演算法,平均情況下已耗用時間為O(n)
此程式利用了快速排序的partition子程式(隨機播放pivot的版本),因為partition總是把比pivot小的劃分到左邊,比pivot大的劃分到右邊,所以利用這一點(但是randomizedSelect不會向快速排序一樣遞迴地處理劃分出來的兩邊,而是只處理左邊或者右邊,因此要更快一些)完成選擇。
此演算法平均效能比較好,因為是隨機化的劃分,不會有哪一組特定的輸入導致其最壞情況的發生。
平均時間是O(n),最壞時間是O(n^2)
實現代碼如下:
1 package algorithms; 2 3 import java.util.Arrays; 4 import java.util.Random; 5 public class SelectionProblem { 6 7 //static StringBuilder logger = new StringBuilder(); // debug 8 //static String NEWLINE = "\n"; // debug 9 10 /**11 * @param a the array12 * @param low the lower bound (inclusive)13 * @param high the upper bound (exclusive)14 * @param i indicate that the i-th order statistic is our target, i starts from 115 * @return the i-th order statistic16 * */17 public static <T extends Comparable<T>>18 T randomizedSelect(T[] a, int low, int high, int i) {19 --high; // high the upper bound (exclusive)20 return _randomizedSelect(a, low, high, i);21 }22 23 private static <T extends Comparable<T>>24 T _randomizedSelect(T[] a, int low, int high, int i) {25 if (low == high) {26 return a[low]; // target found27 }28 // else, partition29 int pivot = randomizedPartition(a, low, high);30 int k = pivot - low + 1;31 if (k == i) { // if pivot is our target32 return a[pivot];33 } else if (k > i) { // if pivot is too large34 return _randomizedSelect(a, low, pivot-1, i);35 } else { // if pivot is too small36 return _randomizedSelect(a, pivot+1, high, i-k);37 }38 }39 40 private static <T extends Comparable<T>>41 int randomizedPartition(T[] a, int low, int high) {42 int pivotIndex = randomIndex(low, high+1);43 // logger.append("pivotIndex:"+pivotIndex+NEWLINE); // debug44 return Partition.doPartition(a, low, high+1, pivotIndex);45 }46 47 private static final Random random = new Random();48 // low (inclusive), high (exclusive)49 private static int randomIndex(int low, int high) {50 if (high==low) {51 return low;52 }53 return random.nextInt(high-low) + low;54 }55 56 // test57 public static void main(String[] args) {58 Integer[] a = new Integer[]{29, 36, 44, 12, 29, 24, 28, 74, 54, 56};59 System.out.println(Arrays.toString(a));60 Integer result = SelectionProblem.randomizedSelect(a, 0, a.length, 10);61 //if (result != 36) { // debug62 // System.out.println(logger); // debug63 //} // debug64 System.out.println("result:"+result);65 //System.out.println(Arrays.toString(a)); // debug66 QuickSort.sort(a, 0, a.length);67 System.out.println(Arrays.toString(a));68 }69 70 }
Selection Problem (選擇問題)