尋找最大的K個數

2022-03-03 18:33:32 字數 1210 閱讀 8224

前提條件:有n個無序的數,假定它們各不相等,如何選出其中最大的若干個數

適用於元素數量不多,記憶體中可儲存整個陣列序列。通過快速排序或堆排序對陣列排序,時間複雜度為o(n*log2n),然後取出前k個數,時間複雜度為o(k),總時間複雜度為o(n*log2n) + o(k),進一步的,可以知道,我們只需要前 k 大的數,所以並不需要對前 k 個數排序,也不需要對後 n - k 個數排序,這樣,通過部分排序的思想,可以選用選擇排序,選出前 k 大的值,總時間複雜度為o(n*k),至於選用哪種方式,根據 k 的大小進行選擇。

適用於元素數量不多,記憶體中可儲存整個陣列序列。根據快速排序的思想,每一步中都是將待排序資料分做兩組,其中一組資料的任一元素都比另一組資料的任一元素大或者小,因此在本問題中,可以考慮,從陣列 s 中隨機選出乙個元素 x ,把陣列分為兩部分 sa 和 sb,sa 的元素大於等於 x,sb的元素小於x。這時,有兩種可能性:

時間複雜度為o(n*log2k)。

適用於元素數量不多,記憶體中可儲存整個陣列序列。尋找 n 個數中最大的 k 個數,其實就是要找出 k 個數中最小的那個,那麼可以通過二分測探的方式,在這 n 個數所在的區間進行探測。假設 n 個數中最大的是 vmax,最小的是 vmin,那麼這 n 個數中的第 k 大數就在區間 [vmin,vmax]之間,在這個區間二分搜尋第 k 大的數。時間複雜度為 o(n*log2n)。

維護乙個 k 大小的堆,當前遍歷的元素比堆中最小元素大,那麼就更新這個堆,最後堆中的 k 個元素就是最大的 k 個數。時間複雜度為o(n*log2k)。這種方法適用於記憶體無法儲存所有的 n 個數。一般情況下,記憶體中都可以維護乙個 k 大小的堆,但是當 k 也特別大,以至於記憶體中無法儲存 k 大小的堆的時候,可以嘗試找出 k『 個元素,然後再找出 k' + 1 到 2k' 的元素,這樣,需要遍歷全部元素 k / k』 趟。

如果所有的元素都是正整數,且其範圍不大,那麼可通過計數排序的思想,來獲得前 k 大的值。比如所有整數都在 [0,max] 區間,那麼通過乙個 cnt[max] 陣列記錄元素出現的次數,然後從大到小取出 k 個最大的元素。在實際情況,往往並不能保證所有數都是正整數,且元素都是小範圍,那麼當元素有正有負,其其範圍涵蓋較廣的情況,可以將元素所在區間 [vmin,vmax] 分成m塊,每個小區間跨度在 (vmax - vmin)/ m,統計各個小區間內元素的個數,可知前 k 大的數在哪個區間,然後再對那個區間進行處理,對小區間處理方式就可參考前面所述的幾種方法了。

以上參考自 《程式設計之美》

尋找最大的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個數

給你n個數,讓你找出其中最大的 k個數。解法1 很多人上來就對其進行排序,選用不同的排序方法有不同的時間複雜度,這裡我們假設使用了最快的快排,時間複雜度為o n logn 通過排序我摘出前 k大的數。但也許快排不是最優的,我們只找最大的k 個數,何必要對所有的數進行排序,我們只需要進行區域性排序即可...