求一個數組中第K小的數


面試南大夏令營的同學說被問到了這個問題,我的第一反應是建小頂堆,但是據他說用的是快排的方法說是O(n)的時間復雜度,

但是后來經過我的考證,這個算法在最壞的情況下是O(n^2)的,但是使用堆在一般情況下是O(n+klogn),最壞的情況是O(nlogn)

把兩種方法整理一下,我還是推薦使用小頂堆的方法,因為它不僅可以求第K大,還可以求前K大。。。

一。快排。借用了快排的partition思想,其實是一種分治的方法。對於一個partition,他左邊的數小於他,右邊的數全大於他

那么:

  1.如果他本身就是第K個數,直接返回。

  2.如果他的下標是比K大的某個數,那么第K小數肯定出現在他左邊。那么到partition的左邊遞歸地求解

  3.如果他的下標是比K小的某個數,那么第K小數肯定出現在他右邊。那么到partition的右邊遞歸地求解

唯一需要注意的地方是,要注意在遞歸的過程中,第K小數是一個相對值,即相對於區間[l,r]的左邊界l;

#include <bits/stdc++.h>
using namespace std; const int maxn = 1000; int a[maxn]; int n = 10,k = 6; int part(int low, int high) { int pivot = a[low]; while(low < high){ while(low < high&&a[high] >= pivot) high--; a[low] = a[high]; while(low < high&&a[low] <= pivot) low++; a[high] = a[low]; } a[low]=pivot; return low; } int quicksort(int l, int r, int k){ int pos = part(l,r); if(pos - l + 1 == k) return a[pos]; else if(pos - l + 1> k) return quicksort(l,pos-1,k); else return quicksort(pos+1,r,k-(pos-l+1)); } int main() { srand((unsigned)time(NULL)); for(int i = 0; i < n; ++i){ a[i] = rand()%(n<<1); } for(int i = 0; i < n; ++i) printf("%d ",a[i]); printf("\n"); int x = quicksort(0,n-1,k); printf("%d\n", x); }

二。小頂堆

使用堆可以求出最小的元素,通過不斷地彈出元素,就可以找到第K大的元素

#include <bits/stdc++.h>
using namespace std; const int maxn = 1000; int a[maxn]; int n,k; void adjust_heap(int rt,int n) { int x=a[rt],pos = rt; while(rt <= n){ int lc = rt << 1,rc = lc|1; if(lc <= n&&a[lc] < x) pos = lc; if(rc <= n&&a[rc] < a[pos]) pos = rc; if(pos == rt) break; a[rt] = a[pos]; rt = pos; } a[pos] = x; } int search_k() { for(int i = n/2;i >= 1; --i){//建堆的復雜度是O(n)的 adjust_heap(i,n); } int sz = n; for(int i = 1; i < k; ++i){//每次彈出要向下調整,調整K次,復雜度為O(Klogn) a[1] = a[sz--]; adjust_heap(1,sz); } return a[1]; } int main() { srand((unsigned)time(NULL)); scanf("%d%d",&n,&k); for(int i = 1; i <= n; ++i){ a[i] = rand()%(n<<1); } for(int i = 1; i <= n; ++i) printf("%d ",a[i]); printf("\n"); int x = search_k(); printf("%d\n", x); }

 


免責聲明!

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



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