快速找出陣列中前k小的元素
阿新 • • 發佈:2018-12-18
方法一:利用快排的思想,迴圈找到第k個位置安放正確的元素,此時k的左邊是小於k位置元素的元素,右邊是大於k位置元素的元素,即前k個元素就是問題答案。時間複雜度O(n)。
int Partition(vector<int> &res,int s,int e) { int tp=res[s]; while(s<e) { while(s<e&&res[e]>=tp)e--; res[s]=res[e]; while(s<e&&res[s]<=tp)s++; res[e]=res[s]; } res[s]=tp; return s; } void GetKNumbers(vector<int> res,int k) { int s=0,e=res.size()-1; int index=Partition(res,s,e); while(index!=k-1) //當k位置安放正確的時候,前k個元素就是最終結果 { if(index>k-1)e=index-1; else s=index+1; index=Partition(res,s,e); } for(int i=0;i<k;i++) cout<<res[i]<<" "; }
方法二:利用堆排序的思想,若找前k小的元素,則構建大頂堆,先將前k個元素構建成大頂堆,然後判斷堆頂元素和第k+i元素,若堆頂元素大則將第k+i位置的元素交換,然後重新調整大頂堆,最後得到的大頂堆就是結果。時間複雜度O(nlogk);
void HeapAdjust(vector<int>&heap,int index) { int tp=heap[index]; for(int i=2*index+1;i<heap.size();i*=2) { if(i<heap.size()-1&&heap[i]<heap[i+1]) i++; if(tp>heap[i])break; heap[index]=heap[i]; index=i; } heap[index]=tp; } void GetKNumbers(vector<int> res,int k) { if(res.size()==0||res.size()<=k||k<=0)return; vector<int> heap(k);//初始化k大小的堆 for(int i=0;i<k;i++) heap[i]=res[i];//首先放入k個元素 for(int i=(k-1)/2;i>=0;--i) HeapAdjust(heap,i);//初始化堆 for(int i=k;i<res.size();i++) {//每次從原陣列中拿出一個元素和當前堆頂值比較, //然後判斷是否可以放入,放入後繼續調整堆結構 if(heap[0]>res[i]){ heap[0]=res[i]; HeapAdjust(heap,0); } } for(int i=0;i<k;i++) cout<<heap[i]<<" "; }