问题:在线性时间内,求一组数中的第k大的数字;
输入:第一行为数字n
第二行输入n个数字
第三行输入k
分析:
1. 首先建立个数组存储这一组数字
2. 随机选取一个数字作为支点
3. 将比支点大的数字放在支点左边
4. 将比支点小的数字放在支点右边
5. 计算支点左边数字的数量
6. 如果数量大于k-1说明第k大的数在支点的左边,在支点的左边重复上述步骤查找
7. 如果数量小于k-1说明第k大的数在支点的右边,在支点的左边重复上述步骤查找
8. 如果数量等于k-1,说明支点就是所求的的第k大的数
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
int a[10005];
int k_find(int low,int high,int k){
if(k<0||k>high-low+1)
return -1;
int pivot=low+rand()%(high+1-low);//需要大一个才能保证取模的范围为数组的范围
swap(a[low],a[pivot]);
int m=low;
int coun=1;
int i,j;
for(i=low+1;i<=high;i++){
if(a[i]>a[low]){
coun++;
swap(a[++m],a[i]);
}
}
swap(a[m],a[low]);
if(coun>k){
k_find(low,m-1,k);
}
else if(coun<k){
k_find(m+1,high,k-coun);
}
else
return m;
}
int main(){
int n;
while(~scanf("%d",&n)){
int i,j;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
int k;
scanf("%d",&k);
k=k_find(0,n-1,k);
if(k!=-1)
printf("%d\n",a[k]);
else
printf("error\n");
}
return 0;
}