17、【常见算法】topN问题
題 目:如果在N個(gè)數(shù)中找出其中前K大的數(shù)?
思路一:
先對(duì)N個(gè)數(shù)進(jìn)行排序,然后在取其前K大的數(shù);(冒泡排序,快速排序等)
思路二:
部分排序,只排除前K大的數(shù)即可(使用選擇排序進(jìn)行部分排序,選擇排序的時(shí)間復(fù)雜度O(N2))
思路三:
我可以用分治法,這有點(diǎn)類似快排中partition的操作。隨機(jī)選一個(gè)數(shù)t,然后對(duì)整個(gè)數(shù)組進(jìn)行partition,會(huì)得到兩部分,前一部分的數(shù)都大于t,后一部分的數(shù)都小于t。
如果說(shuō)前一部分總數(shù)大于1000個(gè),那就繼續(xù)在前一部分進(jìn)行partition尋找。如果前一部分的數(shù)小于1000個(gè),那就在后一部分再進(jìn)行partition,尋找剩下的數(shù)。
該思路的事件復(fù)雜度為O(N):首先,partition的過(guò)程,時(shí)間是o(n)。我們?cè)谶M(jìn)行第一次partition的時(shí)候需要花費(fèi)n,第二次partition的時(shí)候,數(shù)據(jù)量減半了,所以只要花費(fèi)n/2,同理第三次的時(shí)候只要花費(fèi)n/4,以此類推。而n+n/2+n/4+...顯然是小于2n的,所以這個(gè)方法的漸進(jìn)時(shí)間只有o(n)。
思路四:
當(dāng)N的值過(guò)大,且內(nèi)存資源有限,無(wú)法一次讀取全部數(shù)據(jù)時(shí),可以考慮分布式的實(shí)現(xiàn),將數(shù)據(jù)切分,然后在多臺(tái)機(jī)器上分別計(jì)算前K大的數(shù),最后在把這些數(shù)據(jù)匯總。
思路五:
使用最小堆思想。即在內(nèi)存中維護(hù)一個(gè)有K個(gè)數(shù)組成的最小堆;根據(jù)最小堆每一個(gè)節(jié)點(diǎn)都要比他的左右直接點(diǎn)小的性質(zhì):
首先從N個(gè)數(shù)中取K個(gè)數(shù)構(gòu)成最小堆;
然后依次讀取剩余數(shù)據(jù),并且和堆頂元素比較大小,如果比堆頂小,則直接丟棄。如果比堆頂大,就替換堆頂,并調(diào)整最小堆;
所有數(shù)據(jù)都處理完畢后,最小堆就是N個(gè)數(shù)中前K大的數(shù)。
優(yōu)點(diǎn)是:數(shù)據(jù)只需要讀取一次,不會(huì)存在數(shù)據(jù)多次讀寫的問(wèn)題;
【思路五的C++實(shí)現(xiàn)】
【待更新。。。?!?/p>
總結(jié)
以上是生活随笔為你收集整理的17、【常见算法】topN问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: svn authz 授权文件模版
- 下一篇: c# Winform Control 快