給定乙個無序陣列,找出最大的k個數。
以下方法可以解決此類問題。
快速排序中,其中最重要的一步是如何找到某個基準值的最終在陣列的存放位置index,找到這個位置index後,則index左邊的值全小於等於基準值,index右邊的值全大於基準值。在本題中要找top k大的數,那麼過程必須反著來,也即index左邊大於基準值,右邊小於基準值。
那麼我們可以通過比較這個index和k值進行比較:
(1)若sa組的個數大於或等於k,則繼續在sa分組中找取最大的k個數字 。
(2)若sa組中的數字小於k ,其個數為t,則繼續在sb中找取 k-t個數字 。
首先需要找到基準值的位置,通過partition函式實現:
int partition(int a, int left, int right)
return index;
}
求得top k元素
int main()
; int k=3;
int index=findtopknums(a,0,4,k);
for(int i=0;i值得一提的是:考慮到某些陣列元素的特殊性,可以採用random partition,也就是進行劃分的時候,並不是從該陣列的首元素開始,而是隨機乙個下標位置開始
//隨機劃分函式
int randompartition(int a,int left,int right)
上面基於快排partition的方法,有乙個缺點,就是需要比較很多次,而堆排序正是可以減少比較的次數。
該方法的思想:用容量為k的最小堆來儲存最大的k個數,首先對這k個元素的數組建最小堆,那麼堆頂元素a[0]是這k個元素裡面最小的,接著遍歷原始陣列a的剩餘元素,如果比堆頂的元素大,則將其替換堆頂元素,並重新調整此k個元素構成的最小堆。
堆調整:
//該函式調整下標k對應的元素a[k]在小頂堆的位置,下標從0開始
void minheapsift(int a, int k, int n)
遍歷原始陣列,並維護top k陣列
void findtopknums(int a, int topk, int n, int k)
}}
int main()
; int topk[4];
int k=4;
findtopknums(a,topk,5,k);
for(int i=0;i
尋找最大的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...
演算法 尋找最大k個數
對於這個問題,最容易想到的辦法就是給陣列排個序,如果使用快速排序,時間複雜度是o nlogn 但事實上我們只需要尋找這k個數,排序的方法顯然做了多餘的事情。那麼,能不能在這個基礎上優化一下呢?我們知道,快速排序的思想是 在陣列中選中乙個支點,以這個支點將陣列劃分成兩部分s1,s2,保證s1所有元素小...