前言
本文快速回顧了常考的知識點,用作面試複習,事半功倍。
面試知識點複習手冊
通過以下兩種途徑檢視全複習手冊文章導航
- 關注我的公眾號:Rude3Knife 點選公眾號下方:技術推文——面試衝刺
- 全複習手冊文章導航(CSDN)
本文參考
十道海量資料處理面試題與十個方法大總結
https://blog.csdn.net/v_july_v/article/details/6279498
重點:十七道海量資料處理面試題與Bit-map詳解
https://blog.csdn.net/v_july_v/article/details/6685962
有刪減,修改,補充額外增加內容
本作品採用知識共享署名-非商業性使用 4.0 國際許可協議進行許可。
-----正文開始-----
預備知識點
Bitmap和布隆過濾器(Bloom Filter)
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個資料進行排序,然後一遍掃描即可確定相鄰的最大間隙。但該方法不能滿足線性時間的要求。故採取如下方法:
- 找到n個資料中最大和最小資料max和min。
- 用n-2個點等分割槽間[min, max],即將[min, max]等分為n-1個區間(前閉後開區間),將這些區間看作桶,編號為,且桶i 的上界和桶i+1的下屆相同,即每個桶的大小相同。每個桶的大小為:。實際上,這些桶的邊界構成了一個等差數列(首項為min,公差為),且認為將min放入第一個桶,將max放入第n-1個桶。
- 將n個數放入n-1個桶中:將每個元素x[i] 分配到某個桶(編號為index),其中(這括號裡多了個“+”),並求出分到每個桶的最大最小資料。
- 最大間隙:除最大最小資料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
全複習手冊文章導航:通過以下兩種途徑檢視
- 關注我的公眾號:Rude3Knife 點選公眾號下方:技術推文——面試衝刺
- 全複習手冊文章導航(CSDN)
知識點複習手冊文章推薦
- Java基礎知識點面試手冊
- Java容器(List、Set、Map)知識點快速複習手冊
- Java併發知識點快速複習手冊(上)
- Java併發知識點快速複習手冊(下)
- Java虛擬機器知識點快速複習手冊(上)
- Java虛擬機器知識點快速複習手冊(下)
- 快速梳理23種常用的設計模式
- Redis基礎知識點面試手冊
- Leetcode題解分類彙總(前150題)
- 面試常問的小演算法總結
- 查詢演算法總結及其部分演算法實現Python/Java
- 排序演算法實現與總結Python/Java
- HTTP應知應會知識點複習手冊(上)
- HTTP應知應會知識點複習手冊(下)
- 計算機網路基礎知識點快速複習手冊
- ......等(請檢視全複習手冊導航)
關注我
我是蠻三刀把刀,目前為後臺開發工程師。主要關注後臺開發,網路安全,Python爬蟲等技術。
來微信和我聊聊:yangzd1102
Github:https://github.com/qqxx6661
原創部落格主要內容
- 筆試面試複習知識點手冊
- Leetcode演算法題解析(前150題)
- 劍指offer演算法題解析
- Python爬蟲相關技術分析和實戰
- 後臺開發相關技術分析和實戰
同步更新以下部落格
1. Csdn
擁有專欄:
- Leetcode題解(Java/Python)
- Python爬蟲實戰
- Java程式設計師知識點複習手冊
2. 知乎
擁有專欄:
- Java程式設計師面試複習手冊
- LeetCode演算法題詳解與程式碼實現
- 後臺開發實戰
3. 掘金
4. 簡書
個人公眾號:Rude3Knife
如果文章對你有幫助,不妨收藏起來並轉發給您的朋友們~