快速查找无序数组中的第K大数?

时间:2022-06-09 06:07:32

1.题目分析:

查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN)。在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高效算法。

还记得我们快速排序的思想麽?通过“partition”递归划分前后部分。在本问题求解策略中,基于快排的划分函数可以利用“夹击法”,不断从原来的区间[0,n-1]向中间搜索第k大的数,大概搜索方向见下图:

快速查找无序数组中的第K大数?

2.参考代码:

 #include <cstdio>

 #define swap(x,y){int temp=x;x=y;y=temp;}

 using namespace std;

 const int maxn=1e5;

 int a[maxn];

 int part(int *arr,int p,int q){

     int i=p-;

     for(int j=p;j<q;j++) if(arr[j]<a[q]){

         i++;

         swap(arr[i],arr[j]);

     }

     i=i+;

     swap(arr[i],arr[q]);

     return i;

 }

 int findK(int *arr,int n,int k){

     int p=,q=n-;

     while(p<q){

         //int m=p+(q-p)/2;

         int f=part(arr,p,q);

         //printf("f=%d\n",f);   //for tested

         if(f==k){

             return arr[k];

         }else if(f>k){

             q=f-;

         }else{

             p=f+;

         }

     }

     return arr[k]; //needed

 }

 int main(){

     int n,k;

     /*

     *input includes 2 integers. n indicates the num of elements ,

     *k means for the kth larger num to be found

     */

     while(scanf("%d%d",&n,&k)==){

         for(int i=;i<n;i++) scanf("%d",&a[i]);

         int ans=findK(a,n,k-);

         printf("%d\n",ans);

     }

     return ;

 }

 /*

 data for the test:

 4 2

 1 5433 11 2

 4 3

 1 5433 11 2

 4 4

 1 5433 11 2

 */

3.测试结果:

快速查找无序数组中的第K大数?

结语:

本算法实现仅适用常规情况,如果K=1或2聪明的你应该要知道不必套用本文的算法,简单遍历保存最大即可,所以说具体问题还得具体分析^_^