快速查找無序數組中的第K大數?


1.題目分析:

查找無序數組中的第K大數,直觀感覺便是先排好序再找到下標為K-1的元素,時間復雜度O(NlgN)。在此,我們想探索是否存在時間復雜度 < O(NlgN),而且近似等於O(N)的高效算法。

還記得我們快速排序的思想麽?通過“partition”遞歸划分前后部分。在本問題求解策略中,基於快排的划分函數可以利用“夾擊法”,不斷從原來的區間[0,n-1]向中間搜索第k大的數,大概搜索方向見下圖:

2.參考代碼:

 

  1 #include <cstdio>
  2 
  3 #define swap(x,y){int temp=x;x=y;y=temp;}
  4 
  5 using namespace std;
  6 
  7  
  8 
  9 const int maxn=1e5;
 10 
 11 int a[maxn];
 12 
 13  
 14 
 15 int part(int *arr,int p,int q){
 16 
 17     int i=p-1;
 18 
 19     for(int j=p;j<q;j++) if(arr[j]<a[q]){
 20 
 21         i++;
 22 
 23         swap(arr[i],arr[j]);
 24 
 25     }
 26 
 27     i=i+1;
 28 
 29     swap(arr[i],arr[q]);
 30 
 31     return i;
 32 
 33 }
 34 
 35 int findK(int *arr,int n,int k){
 36 
 37     int p=0,q=n-1;
 38 
 39     while(p<q){
 40 
 41         //int m=p+(q-p)/2;
 42 
 43         int f=part(arr,p,q);
 44 
 45         //printf("f=%d\n",f);   //for tested
 46 
 47         if(f==k){
 48 
 49             return arr[k];
 50 
 51         }else if(f>k){
 52 
 53             q=f-1;
 54 
 55         }else{
 56 
 57             p=f+1;
 58 
 59         }
 60 
 61     }
 62 
 63     return arr[k]; //needed
 64 
 65 }
 66 
 67 int main(){
 68 
 69     int n,k;
 70 
 71     /*
 72 
 73     *input includes 2 integers. n indicates the num of elements ,
 74 
 75     *k means for the kth larger num to be found
 76 
 77     */
 78 
 79     while(scanf("%d%d",&n,&k)==2){
 80 
 81         for(int i=0;i<n;i++) scanf("%d",&a[i]);
 82 
 83         int ans=findK(a,n,k-1);
 84 
 85         printf("%d\n",ans);
 86 
 87     }
 88 
 89     return 0;
 90 
 91 }
 92 
 93 /*
 94 
 95 data for the test:
 96 
 97 4 2
 98 
 99 1 5433 11 2
100 
101 4 3
102 
103 1 5433 11 2
104 
105 4 4
106 
107 1 5433 11 2
108 
109 */
110 
111  

 

3.測試結果:

 

 

結語:

本算法實現僅適用常規情況,如果K=12聰明的你應該要知道不必套用本文的算法,簡單遍歷保存最大即可,所以說具體問題還得具體分析^_^

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM