題目描述:有很多無序的數,姑且家丁它們各不相等,怎麼選出其中最大的若干個數呢?這裡我不想去寫一些很沒有意義的思路。神馬先排序取前k個這種弱爆了並且一點也不適用的思想我就不想廢話了,因為如果資料量很大的時候,對所有資料排序肯定是費力不討好的事情,換換思路,不能全部排序,那就部分排序吧!這裡介紹兩個比較實用的。當然為了有點遞進關係,先來乙個比較差一點的方法。如果對排序演算法還不是很熟悉的,可以參考部落格:排序演算法
。
1、快排。回憶一下快排的思想,選乙個關鍵元素key,利用key將陣列分成兩部分,左邊一部分比key大,右邊一部分比key小(當然本身的定義是左邊一部分比key小,右邊一部分比key大),那麼key的位置有下面三種情況:
*如果key正好放在第k個數的位置上面,ok,那說明前k大的數我們已經找到了,就不需要排序了。
*如果key的位置比k小,那說明前面找到的最大的元素中還不足k個,那就在後面一段的資料中繼續找。
*如果key的位置比k小,那說明前面找到的最大的元素的個數超過k了,那就在前面的一段資料中分出k個就不可以了。
如果是需要找最小的k個元素,類似的思想,這裡就不廢話了。**如下:
void quicksort(int *arr, int begin, int end, int k)
arr[i] = key;
if(i == k - 1)//恰好k個,返回
return;
else if(i < k - 1)//不足k個,在後面繼續找
quicksort(arr, i + 1, end, k);
else//多於k個,在前面分出k個
quicksort(arr, begin, i - 1, k);
}
2、堆排序。如果資料量很多的時候,快排有個什麼壞處呢?它需要將所有資料都一次匯入記憶體,在海量資料的情況下,顯然是不能做到的,但是堆排序就可以。如果我們需要找最大的k個數,那就維護乙個由k個數組成的最小堆,堆頂元素是堆的最小值。每次進來乙個數,先與堆頂元素比較,如果小於堆頂元素,那一定小於堆中的任何乙個元素。如果大於堆頂元素,ok,用這個數替換堆頂元素,然後調整新得到的堆。**如下:
//將開始元素s到nlen組成的堆調整為最小堆
void minheapadjust(int *arr, int s, int nlen)
arr[s] = t;
}
3、給出兩種方法的main函式呼叫,如果不需要,可以直接pass掉。
//列印陣列
void print(int *arr, int nlen)
int main()
*/ //堆排序main函式的呼叫部分
while(scanf("%d %d", &n, &k) != eof)
}print(&arr[1], k);
}}
程式設計之美之尋找最大的k個數
這個題目很常見,方法也很多,這裡總結了程式設計之美給出的幾個比較好的方法,也算是對這個問題的乙個總結。方法一 partition演算法,每次partition的複雜度為o n 總的平均時間複雜度為o nlogn 分析 運用partition演算法,如果返回的provit k 1,則說明要找的數都在前...
程式設計之美 尋找最大的K個數
有很多個無序數,我們姑且假定他們各不相等,怎麼挑選出其中最大的若干個數呢?如果這個資料量很大,比如1億個,如果所存資料是浮點型呢?我們該怎麼處理呢?分兩部分,第一部分是我個人的解答,第二部分是書上的解答 第一部分 1,如果這個問題裡的資料都是整數,這個問題利用hash對映應該很簡單,就是在開闢乙個陣...
程式設計之美 尋找最大的K個數
有很多個無序數,我們姑且假定他們各不相等,怎麼挑選出其中最大的若干個數呢?如果這個資料量很大,比如1億個,如果所存資料是浮點型呢?我們該怎麼處理呢?分兩部分,第一部分是我個人的解答,第二部分是書上的解答 第一部分 1,如果這個問題裡的資料都是整數,這個問題利用hash對映應該很簡單,就是在開闢乙個陣...