题目:输入n个整数和一个正整数k(0<=k<= n),输出这些整数从小到大排序后的第k个。n<=10^7。
首先我们可以先排序,然后返回a[k]。但是这样普通排序O(n^2)的复杂度是无法承受的,用O(nlogn)的排序方法,然后返回a[k]。有没有更高效的方法呢?有的,用快速排序,首先第一趟划分后,假设划分的位置为pos,那个左边有pos-1个数比他小。如果k==pos那么直接返回a[pos]。如果k<pos,那么kth_element肯定在左半边的数中,这样我们可以丢掉右边这些数据。同理如果k>pos,那么kth_elemetn则是在右边那些数中,这样把左边的数丢掉。这样的做我们只递归左半部分或者右半部分,复杂度为O(n)。下面是我写的模板,划分的方法采用一个比较简单的划分方法,网上还有hoare划分的方法,原理都一样。
int kth_element(int *a, int l, int r, int k){
if(l < r){
int key = a[r];
int i = l-1;
for(int j = l; j < r; j ++){
if(a[j] < key){
i ++;
swap(a[i], a[j]);
}
}
swap(a[i+1], a[r]);
if(k == i+1) return a[i+1];
else if(k < i+1) kth_element(a, l, i, k);
else kth_element(a, i+2, r, k);
}
}