與此相似的題目是:
- 求第k大的數
- 求第k小的數
這裡給出比較好的兩個做法,分別是快排思想和堆思想,至於怎麼做的這裡就不重述了,直接上**。
int quicksort_cut(int arr,int left,int right)
int i,j,temp;
i = left; j = right;
temp = arr[left];
while(iwhile(temp > arr[j] && i < j)
j--;
if (iwhile(temp <= arr[i] && i < j)
i++;
if (i//此時 i==j
arr[i] = temp;
return i;
}int get_k_bigs(int arr,int left,int right,int k)
//劃分,返回劃分位置.
cut_index = quicksort_cut(arr,left,right);
n = cut_index - left +1;
if (k == n)
else
if (n//如果小於k個,還要在右邊拿k-n個
else
//如果大於k個,則範圍縮小為left--cut_index
}
測試**:
int main()
; vector
* result;
int x = get_k_bigs(a,0,7,4);
result = new
vector
(a,a+x+1);
for (vector
::iterator iter = result->begin();iter != result->end();iter++)
cout
<< endl;
delete result;
system("pause");
return
0;}
用容量為k的最小堆來儲存最大的k個數。最小堆的堆頂元素就是最大k個數中的最小的乙個。每次掃瞄乙個資料x,如果x比堆頂元素y小,則不需要改變原來的堆,因為這個元素比最大的k個數要小。如果x比堆頂元素大,那麼用x替換堆頂元素y,在替換之後,x可能破壞了最小堆的結構,需要調整堆來維持堆的性質。調整過程時間複雜度為o(logk)。實現:當資料量很大時(這時候資料已經不能全部裝入記憶體,所以要求盡可能少的遍歷陣列)可以採用這種方法。
//index:調整的堆節點;n:堆元素個數;該函式只調整乙個節點。
//index,必須是從1開始算起。
void min_heap_shift(int a,int
index,int n)
else
}a[i] = temp;
} /*
* 建堆:將乙個陣列a[1~k]變成乙個最小堆
* 避免額外空間,就在原來陣列中建
*/void build_min_heap(int a,int k)
} /*
*注意arr是從1開始的。
*k表示要提取的最大的k個數
*n表示a陣列從1開始的長度
*/void get_k_bigs(int a,int k,int n)
int i;
build_min_heap(a,k);
for (i = n;i>k;i--)
}}
測試**:
int main()
; get_k_bigs(a,k,n);
for(int i = 1;i <= k;i++)
system("pause");
return
0;}
其實,這道題給我的感觸是蠻深的,知識的遷移,知識的靈活應用,都是很好的鍛鍊,最基本的鍛鍊了我對快排和堆排的理解。
最後,感謝(這篇博文講述!
尋找最小k個數或者尋找第K大的數字
輸入n個整數,找出最小的前k個數字 或者第k大的數字 例如輸入4,5,1,6,2,7,3,8這八個數,則輸出最小4個數是1,2,3,4.o n 解法,需要修改輸入陣列。可以採用快速排序partition函式來解決這個問題。快排的partition函式所完成的功能是將小於pivot的數放在partit...
尋找最大的K個數
方法一 改進的快速排序 分割槽時,根據數p將陣列分為兩部分,設大於p的數個數為a,小於p的數的個數為b。如果,a k,則從這a個數取最大的k個數,若a時間複雜度是o nlogk include includevoid swap float a,float b int fun float n,int ...
尋找最大的K個數
程式設計之美有一道考察多種排序的題目,題目如下 有乙個長度為n的無序陣列,假定其中的每乙個元素都各不相等,求其中最大的k個數。作者對於此題目結合各種排序演算法給出了五種解法思路。解法一 使用快速排序或堆排序對它們元素進行排序,整個排序的時間複雜度為o n lo g2n 然後取出前k個,時間複雜度為o...