原理
分治思想的强大又一次体现出来了。这种选择算法可以筛选出大小为n的序列中第i(i <= n)大的元素。特别的,也可以求中位数。find方法实现原理如同快速排序的划分阶段,唯一的区别是该方法为了找到目标元素递归调用自身。p>=r为基本情况。find方法遍历元素的过程中,array数组一直保持这样的三种状态直到遍历结束:
[ array[j] < pivot的元素| array[j] > pivot的元素| 未遍历到的元素]
该过程也可证明算法的正确性。算法的期望时间复杂度为O(N)。find方法中,循环部门,可能每次pivot都是最大元素,这样的话,find方法的复杂度为O(N),多次find都如此的话,则出现复杂度为O(N^2)的最坏情况。
实现
/**
* Created by tiantian on 2018/8/27
*/
public class RandomSelect {
private static int index = 2;
private static Integer target = null;
public static void find(Integer[] array, int p, int r) {
if (p >= r) {
return;
}
Integer pivot = array[r];
int i = p - 1;
for (int j = p; j < r; j++) {
if (array[j] <= pivot) {
i++;
exchange(array, i, j);
}
}
exchange(array, i+1, r);
if (i+1 == index) {
target = array[i+1];
System.out.println(target);
return;
} else if (i+1 > index) {
find(array, p, i);
} else {
find(array, 1,r);
}
}
public static void exchange(Integer[] array, int a, int b) {
Integer temp = array[a];
array[a] = array[b];
array[b] = temp;
}
public static void main(String[] args) {
Integer[] array = {5,10,25,18,200,4,29,12,50,22,23,8,51,1,9,90,26,3,9,30};
find(array, 0, array.length-1);
}
}