海量數據處理問題知識點複習手冊

在這裏插入圖片描述

前言

本文快速回顧了常考的知識點,用做面試複習,事半功倍。html

面試知識點複習手冊

經過如下兩種途徑查看全複習手冊文章導航c++

本文參考

十道海量數據處理面試題與十個方法大總結git

https://blog.csdn.net/v_july_v/article/details/6279498程序員

重點:十七道海量數據處理面試題與Bit-map詳解github

https://blog.csdn.net/v_july_v/article/details/6685962面試

有刪減,修改,補充額外增長內容算法

本做品採用知識共享署名-非商業性使用 4.0 國際許可協議進行許可。數據庫

-----正文開始-----

預備知識點

Bitmap和布隆過濾器(Bloom Filter)windows

https://blog.csdn.net/zdxiq000/article/details/57626464設計模式

Bitmap

咱們只想知道某個元素出現過沒有。若是爲每一個全部可能的值分配1個bit,32bit的int全部可能取值須要內存空間爲:

2^32bit=2^29Byte=512MB

但對於海量的、取值分佈很均勻的集合進行去重,Bitmap極大地壓縮了所須要的內存空間。於此同時,還額外地完成了對原始數組的排序工做。缺點是,Bitmap對於每一個元素只能記錄1bit信息,若是還想完成額外的功能,恐怕只能靠犧牲更多的空間、時間來完成了。

Bloom Filter

若是說Bitmap對於每個可能的整型值,經過直接尋址的方式進行映射,至關於使用了一個哈希函數,那布隆過濾器就是引入了k(k>1)個相互獨立的哈希函數,保證在給定的空間、誤判率下,完成元素判重的過程。下圖中是k=3時的布隆過濾器。

在這裏插入圖片描述

那麼布隆過濾器的偏差有多少?咱們假設全部哈希函數散列足夠均勻,散列後落到Bitmap每一個位置的機率均等。

在這裏插入圖片描述

若以m=16nm=16n計算,Bitmap集合的大小爲238bit=235Byte=32GB238bit=235Byte=32GB,此時的ε≈0.0005。而且要知道,以上計算的都是偏差的上限。

布隆過濾器經過引入必定錯誤率,使得海量數據判重在能夠接受的內存代價中得以實現。從上面的公式能夠看出,隨着集合中的元素不斷輸入過濾器中(nn增大),偏差將愈來愈大。可是,當Bitmap的大小mm(指bit數)足夠大時,好比比全部可能出現的不重複元素個數還要大10倍以上時,錯誤機率是能夠接受的。

這裏有一個google實現的布隆過濾器,咱們來看看它的誤判率:

在這個實現中,Bitmap的集合m、輸入的原始數集合n、哈希函數k的取值都是按照上面最優的方案選取的,默認狀況下保證誤判率ε=0.5k<0.03≈0.55,於是此時k=5。

而還有一個頗有趣的地方是,實際使用的卻並非5個哈希函數。實際進行映射時,而是分別使用了一個64bit哈希函數的高、低32bit進行循環移位。註釋中包含着這個算法的論文「Less Hashing, Same Performance: Building a Better Bloom Filter」,論文中指明其對過濾器性能沒有明顯影響。很明顯這個實現對於m>232時的支持並很差,由於當大於231−1的下標在算法中並不能被映射到。

海量數據問題解題思路

參考:https://blog.csdn.net/luochoudan/article/details/53736752

我的將這些題分紅了兩類:一類是容易寫代碼實現的;另外一類側重考察思路的。毫無疑問,後一種比較簡單,你只要記住它的應用場景、解決思路,並能在面試的過程當中將它順利地表達出來,便能以不變應萬變。前一種,須要手寫代碼,就必需要掌握必定的技巧,常見的解法有兩種,就是前面說過的堆排和快排的變形。

  • 堆排序:我認爲不用變形,會原始堆排序就行。
  • 快排變形(找到最大的TopK): 當len(ary) - K == key or len(ary) - K == key + 1時就獲得了最大的K個數。

注意點:

  • 分小文件:hash後直接存儲原來的值,而不是將hash值分到各個文件中。
  • 單位換算:一字節8bit

經典題目:

序號對應於參考網頁:

https://blog.csdn.net/v_july_v/article/details/6685962

hash後將海量數據分到另外的小文件中,分別處理,最後再歸併

1.2.3.4.7.8.11.13

經典例題:2

有10個文件,每一個文件1G,每一個文件的每一行存放的都是用戶的query,每一個文件的query均可能重複。要求你按照query的頻度排序。

方案1:

順序讀取10個文件,按照hash(query)%10的結果將query寫入到另外10個文件(記爲)中。這樣新生成的文件每一個的大小大約也1G(假設hash函數是隨機的)。 找一臺內存在2G左右的機器,依次對用hash_map(query, query_count)來統計每一個query出現的次數。利用快速/堆/歸併排序按照出現次數進行排序。將排序好的query和對應的query_cout輸出到文件中。這樣獲得了10個排好序的文件(,此處有誤,更正爲b0,b1,b2,b9)。 對這10個文件進行歸併排序(內排序與外排序相結合)。

方案2:

通常query的總量是有限的,只是重複的次數比較多而已,可能對於全部的query,一次性就能夠加入到內存了。這樣,咱們就能夠採用trie樹/hash_map等直接來統計每一個query出現的次數,而後按出現次數作快速/堆/歸併排序就能夠了

bitmap直接映射

經典例題:5

在2.5億個整數中找出不重複的整數,內存不足以容納這2.5億個整數。

方案1:採用2-Bitmap(每一個數分配2bit,00表示不存在,01表示出現一次,10表示屢次,11無心義)進行,共需內存2^32*2bit=1GB內存,還能夠接受。而後掃描這2.5億個整數,查看Bitmap中相對應位,若是是00變01,01變10,10保持不變。所描完過後,查看bitmap,把對應位是01的整數輸出便可。

方案2:也可採用上題相似的方法,進行劃分小文件的方法。而後在小文件中找出不重複的整數,並排序。而後再進行歸併,注意去除重複的元素。

最大最小堆

經典例題:6

海量數據分佈在100臺電腦中,想個辦法高效統計出這批數據的TOP10。

在每臺電腦上求出TOP10,能夠採用包含10個元素的堆完成(TOP10小,用最大堆,TOP10大,用最小堆)。好比求TOP10大,咱們首先取前10個元素調整成最小堆,若是發現,而後掃描後面的數據,並與堆頂元素比較,若是比堆頂元素大,那麼用該元素替換堆頂,而後再調整爲最小堆。最後堆中的元素就是TOP10大。

桶排序

經典例題:15

給定n個實數,求着n個實數在實軸上向量2個數之間的最大差值,要求線性的時間算法。

方案1:最早想到的方法就是先對這n個數據進行排序,而後一遍掃描便可肯定相鄰的最大間隙。但該方法不能知足線性時間的要求。故採起以下方法:

  1. 找到n個數據中最大和最小數據max和min。
  2. 用n-2個點等分區間[min, max],即將[min, max]等分爲n-1個區間(前閉後開區間),將這些區間看做桶,編號爲,且桶i 的上界和桶i+1的下屆相同,即每一個桶的大小相同。每一個桶的大小爲:。實際上,這些桶的邊界構成了一個等差數列(首項爲min,公差爲),且認爲將min放入第一個桶,將max放入第n-1個桶。
  3. 將n個數放入n-1個桶中:將每一個元素x[i] 分配到某個桶(編號爲index),其中(這括號裏多了個「+」),並求出分到每一個桶的最大最小數據。
  4. 最大間隙:除最大最小數據max和min之外的n-2個數據放入n-1個桶中,由抽屜原理可知至少有一個桶是空的,又由於每一個桶的大小相同,因此最大間隙不會在同一桶中出現,必定是某個桶的上界和睦候某個桶的下界之間隙,且該量筒之間的桶(即使好在該連個便好之間的桶)必定是空桶。也就是說,最大間隙在桶i的上界和桶j的下界之間產生j>=i+1。一遍掃描便可完成。

並查集

經典例題:16

TopK問題(注重代碼實現)

經典例題:12

100w個數中找出最大的100個數。

方案1:採用局部淘汰法。選取前100個元素,並排序,記爲序列L。而後一次掃描剩餘的元素x,與排好序的100個元素中最小的元素比,若是比這個最小的要大,那麼把這個最小的元素刪除,並把x利用插入排序的思想,插入到序列L中。依次循環,知道掃描了全部的元素。複雜度爲O(100w*100)。

方案2:採用快速排序的思想,每次分割以後只考慮比軸大的一部分,知道比軸大的一部分在比100多的時候,採用傳統排序算法排序,取前100個。複雜度爲O(100w100)。 方案3:在前面的題中,咱們已經提到了,用一個含100個元素的最小堆完成。複雜度爲O(100wlg100)。

字典樹Tire樹

經典例題:3.9.10

有一個1G大小的一個文件,裏面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。

方案1:順序讀文件中,對於每一個詞x,取,而後按照該值存到5000個小文件(記爲)中。這樣每一個文件大概是200k左右。若是其中的有的文件超過了1M大小,還能夠按照相似的方法繼續往下分,直到分解獲得的小文件的大小都不超過1M。對每一個小文件,統計每一個文件中出現的詞以及相應的頻率(能夠採用trie樹/hash_map等),並取出出現頻率最大的100個詞(能夠用含100個結點的最小堆),並把100詞及相應的頻率存入文件,這樣又獲得了5000個文件。下一步就是把這5000個文件進行歸併(相似與歸併排序)的過程了。

求中位數

經典例題:14

一共有N個機器,每一個機器上有N個數。每一個機器最多存O(N)個數並對它們操做。如何找到N^2個數中的中數?

方案1:先大致估計一下這些數的範圍,好比這裏假設這些數都是32位無符號整數(共有2^32個)。咱們把0到2^32-1的整數劃分爲N個範圍段,每一個段包含(2^32)/N個整數。好比,第一個段位0到2^32/N-1,第二段爲(2^32)/N到(2^32)/N-1,…,第N個段爲(2^32)(N-1)/N到2^32-1。而後,掃描每一個機器上的N個數,把屬於第一個區段的數放到第一個機器上,屬於第二個區段的數放到第二個機器上,…,屬於第N個區段的數放到第N個機器上。注意這個過程每一個機器上存儲的數應該是O(N)的。下面咱們依次統計每一個機器上數的個數,一次累加,直到找到第k個機器,在該機器上累加的數大於或等於(N^2)/2,而在第k-1個機器上的累加數小於(N^2)/2,並把這個數記爲x。那麼咱們要找的中位數在第k個機器中,排在第(N^2)/2-x位。而後咱們對第k個機器的數排序,並找出第(N^2)/2-x個數,即爲所求的中位數的複雜度是O(N^2)的。

方案2:先對每臺機器上的數進行排序。排好序後,咱們採用歸併排序的思想,將這N個機器上的數歸併起來獲得最終的排序。找到第(N^2)/2個即是所求。複雜度是O(N^2*lgN^2)的。

補充題目:在10G的數據中找出中位數

不妨假設10G個整數是64bit的。 2G內存能夠存放256M個64bit整數。 咱們能夠將64bit的整數空間平均分紅256M個取值範圍,用2G的內存對每一個取值範圍內出現整數個數進行統計。這樣遍歷一邊10G整數後,咱們便知道中數在那個範圍內出現,以及這個範圍內總共出現了多少個整數。 若是中數所在範圍出現的整數比較少,咱們就能夠對這個範圍內的整數進行排序,找到中數。若是這個範圍內出現的整數比較多,咱們還能夠採用一樣的方法將此範圍再次分紅多個更小的範圍(256M=2^28,因此最多須要3次就能夠將此範圍縮小到1,也就找到了中數)。

補充的知識:

AVL樹 最先的平衡二叉樹之一。應用相對其餘數據結構比較少。windows對進程地址空間的管理用到了avl樹。

紅黑樹 平衡二叉樹,普遍用在c++的stl中。如map和set都是用紅黑樹實現的。

b/b+樹 用在磁盤文件組織 數據索引和數據庫索引。

trie樹(字典樹): 用在統計和排序大量字符串,如自動機。

參考:

http://www.cnblogs.com/huangxincheng/archive/2012/11/25/2788268.html

https://blog.csdn.net/hihozoo/article/details/51248823 (裏面Trie樹的應用寫的很好)

-----正文結束-----

更多精彩文章,請查閱個人博客或關注個人公衆號:Rude3Knife

全複習手冊文章導航:經過如下兩種途徑查看

知識點複習手冊文章推薦

關注我

我是蠻三刀把刀,目前爲後臺開發工程師。主要關注後臺開發,網絡安全,Python爬蟲等技術。

來微信和我聊聊:yangzd1102

Github:https://github.com/qqxx6661

原創博客主要內容

  • 筆試面試複習知識點手冊
  • Leetcode算法題解析(前150題)
  • 劍指offer算法題解析
  • Python爬蟲相關技術分析和實戰
  • 後臺開發相關技術分析和實戰

同步更新如下博客

1. Csdn

blog.csdn.net/qqxx6661

擁有專欄:

  • Leetcode題解(Java/Python)
  • Python爬蟲實戰
  • Java程序員知識點複習手冊

2. 知乎

www.zhihu.com/people/yang…

擁有專欄:

  • Java程序員面試複習手冊
  • LeetCode算法題詳解與代碼實現
  • 後臺開發實戰

3. 掘金

juejin.im/user/5b4801…

4. 簡書

www.jianshu.com/u/b5f225ca2…

我的公衆號:Rude3Knife

我的公衆號:Rude3Knife

若是文章對你有幫助,不妨收藏起來並轉發給您的朋友們~

相關文章
相關標籤/搜索