海量數據中找top K專題


1. 10億個數中找出最大的1000個數

這種題目就是分治+堆排序。

為啥分治?因為數太多了,全部加載進內存不夠用,所以分配到多台機器中,或者多個文件中,但具體分成多少份,視情況而定,只要保證滿足內存限制即可。什么,如何分?Hash(num)% numOfFiles。

為啥堆排序?首先堆排序是一種選擇排序,比一般的選擇排序時間復雜度要低,額外的空間復雜度都是O(1)。因為我只要在每一份中拿出最大的1000個即可,這里用大頂堆還是小頂堆呢?

開始我覺得是大頂堆,我們不妨舉個例子:假設10億個數,分成若干組,每組假設1000000,我們所要做的,就是在這1000000的個數中,找出前1000。如果采用大頂堆,意味着我們需要構建1000000節點的一個大樹,然后調整找出前1000,就是根嘛。但是你不覺得這個樹太大了嗎?而要是小頂堆呢?我只要構建一個1000節點的樹即可,這樣我從剩余元素中拿出來和根比較,如果比根小直接舍棄,如果比根大,替換根的位置,然后重新調整堆,這樣最后這1000個節點就是最大的。

最后把每一份中的1000個最大的數合在一起找最終結果就夠了(可以繼續用堆排序查找),有沒有覺得這個就是mapReduce的Shuffle的思想,如果不了解建議看一下我的另一篇博客:http://www.cnblogs.com/DarrenChan/p/6477088.html,不同的是Shuffle中合並排序采用的是歸並排序。

堆排序講解,請參考:https://www.cnblogs.com/chengxiao/p/6129630.html

2. 10億個數中找出出現頻率最高的1000個數

這道題和上道題本質相同,通常比較好的方案是分治+Trie樹/hash+堆排序,即先將數據集按照Hash方法分解成多個小數據集,然后使用Trie樹或者Hash統計每個數字的詞頻,之后用堆排序求出每個數據集中出現頻率最高的前K個數,最后再合並求最終的top K。

3. 10億個數中找出某個數

我剛開始的想法是分治+排序,然后每個二分查找,可是感覺還是復雜度蠻高的。

后來突然想到MySQL數據庫中的索引,就想成給主鍵建立索引,然后查找主鍵不就好了嗎?

參考InnoDB數據庫索引的思路,建立一個主鍵索引,這里不用建立輔助索引了,因為你只有主鍵,哈哈~然后索引通過B+樹進行存儲,為什么采用B+樹,主要為了減少IO次數,為啥不用B-樹(B樹),額,定義上好像說了,請看:

B+樹是B樹的一個升級版,相對於B樹來說B+樹更充分的利用了節點的空間,讓查詢速度更加穩定,其速度完全接近於二分法查找。為什么說B+樹查找的效率要比B樹更高、更穩定;我們先看看兩者的區別:

(1)B+跟B樹不同B+樹的非葉子節點不保存關鍵字記錄的指針,這樣使得B+樹每個節點所能保存的關鍵字大大增加;

(2)B+樹葉子節點保存了父節點的所有關鍵字和關鍵字記錄的指針,每個葉子節點的關鍵字從小到大鏈接;

(3)B+樹的根節點關鍵字數量和其子節點個數相等;

(4)B+的非葉子節點只進行數據索引,不會存實際的關鍵字記錄的指針,所有數據地址必須要到葉子節點才能獲取到,所以每次數據查詢的次數都一樣;

 

特點:

在B樹的基礎上每個節點存儲的關鍵字數更多,樹的層級更少所以查詢數據更快,所有指關鍵字指針都存在葉子節點,所以每次查找的次數都相同所以查詢速度更穩定;

具體參見:https://zhuanlan.zhihu.com/p/27700617

這樣我們就可以通過索引在葉子節點查詢到我們的數字了。

 

參考:https://blog.csdn.net/zyq522376829/article/details/47686867


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM