求N個無序數(shù)組中第K(大/小)數(shù)的方法

思路一:時間復(fù)雜度為O(N*logk)

對前k個數(shù),建立最大堆,對于后面N-k個數(shù),依次和最大堆的最大數(shù)比較,如果小于最大數(shù),則替換最大數(shù),并重新建立最大堆。

堆排序:

我們舉例,假若從10000萬個數(shù)里選出前100個最大的數(shù)據(jù)。
首先我們先分析:既然要選出前100個最大的數(shù)據(jù),我們就建立一個大小為100的堆(建堆時就按找最大堆的規(guī)則建立,即每一個根節(jié)點都大于它的子女節(jié)點),然后再將后面的剩余數(shù)據(jù)若符合要求就插入堆中,不符合就直接丟棄該數(shù)據(jù)。
那我們現(xiàn)在考慮:確定是該選擇最大堆的數(shù)據(jù)結(jié)構(gòu)還是最小堆的數(shù)據(jù)結(jié)構(gòu)呢。
分析一下:
若選用最大堆的話,堆頂是堆的最大值,我們考慮既然要選出從10000萬個數(shù)里選出前100個最大的數(shù)據(jù),我們在建堆的時候,已經(jīng)考慮了最大堆的特性,那這樣的話最大的數(shù)據(jù)必然在它頂端。假若真不巧,我開始的前100個數(shù)據(jù)中已經(jīng)有這10000個數(shù)據(jù)中的最大值了,那對于我后面剩余的10000-100的元素再想入堆是不是入不進(jìn)去了?。?!所以,選用最大堆從10000萬個數(shù)里選出前100個最大的數(shù)據(jù)只能找出一個,而不是100個。
那如果選用最小堆的數(shù)據(jù)結(jié)構(gòu)來解決,最頂端是最小值,再次遇到比它大的值,就可以入堆,入堆后重新調(diào)整堆,將小的值pass掉。這樣我們就可以選出最大的前K個數(shù)據(jù)了。言外之意,假若我們要找出N個數(shù)據(jù)中最小的前k個數(shù)據(jù),就要用最大堆了。
那如果選用最小堆的數(shù)據(jù)結(jié)構(gòu)來解決,最頂端是最小值,再次遇到比它大的值,就可以入堆,入堆后重新調(diào)整堆,將小的值pass掉。這樣我們就可以選出最大的前K個數(shù)據(jù)了。

時間復(fù)雜度:n*logk

一個堆的元素數(shù)目為K時,堆的高度至多為logk。建立堆的時間為klogk。而調(diào)整的次數(shù)為n-k,每次調(diào)整的時間為logk,所以調(diào)整的時間為 (n-k)logk,所以總的時間復(fù)雜度為nlogk。
n
logk = klogk + (n-k)logk

假若我們要找出N個數(shù)據(jù)中最大的前k個數(shù)據(jù),就要用最小頂堆了。
假若我們要找出N個數(shù)據(jù)中最小的前k個數(shù)據(jù),就要用最大頂堆了。

思路二:時間復(fù)雜度為O(k*n)

先排序前k個數(shù),對于后面N-k個數(shù),依次進(jìn)行插入。
當(dāng)k很小時,可以用這種算法

思路三:復(fù)雜度O(N*logN).

先直接排序,再取排序后數(shù)據(jù)的前k個數(shù)。
排序算法用最快的堆排序,復(fù)雜度也會達(dá)到O(N*logN).
當(dāng)k接近于N時,可以用這種算法。

引自:https://blog.csdn.net/hanjing_1995/article/details/51539593
引自:http://www.cnblogs.com/studynote/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容