海量数据处理问题知识点复习手册
前言
本文快速回顧了??嫉闹R點,用作面試復習,事半功倍。
面試知識點復習手冊
通過以下兩種途徑查看全復習手冊文章導航
- 關注我的公眾號:Rude3Knife 點擊公眾號下方:技術推文——面試沖刺
- 全復習手冊文章導航(CSDN)
本文參考
十道海量數(shù)據(jù)處理面試題與十個方法大總結
https://blog.csdn.net/v_july_v/article/details/6279498
重點:十七道海量數(shù)據(jù)處理面試題與Bit-map詳解
https://blog.csdn.net/v_july_v/article/details/6685962
有刪減,修改,補充額外增加內(nèi)容
本作品采用知識共享署名-非商業(yè)性使用 4.0 國際許可協(xié)議進行許可。
-----正文開始-----
預備知識點
Bitmap和布隆過濾器(Bloom Filter)
https://blog.csdn.net/zdxiq000/article/details/57626464
Bitmap
我們只想知道某個元素出現(xiàn)過沒有。如果為每個所有可能的值分配1個bit,32bit的int所有可能取值需要內(nèi)存空間為:
232bit=229Byte=512MB
但對于海量的、取值分布很均勻的集合進行去重,Bitmap極大地壓縮了所需要的內(nèi)存空間。于此同時,還額外地完成了對原始數(shù)組的排序工作。缺點是,Bitmap對于每個元素只能記錄1bit信息,如果還想完成額外的功能,恐怕只能靠犧牲更多的空間、時間來完成了。
Bloom Filter
如果說Bitmap對于每一個可能的整型值,通過直接尋址的方式進行映射,相當于使用了一個哈希函數(shù),那布隆過濾器就是引入了k(k>1)個相互獨立的哈希函數(shù),保證在給定的空間、誤判率下,完成元素判重的過程。下圖中是k=3時的布隆過濾器。
那么布隆過濾器的誤差有多少?我們假設所有哈希函數(shù)散列足夠均勻,散列后落到Bitmap每個位置的概率均等。
若以m=16nm=16n計算,Bitmap集合的大小為238bit=235Byte=32GB238bit=235Byte=32GB,此時的ε≈0.0005。并且要知道,以上計算的都是誤差的上限。
布隆過濾器通過引入一定錯誤率,使得海量數(shù)據(jù)判重在可以接受的內(nèi)存代價中得以實現(xiàn)。從上面的公式可以看出,隨著集合中的元素不斷輸入過濾器中(nn增大),誤差將越來越大。但是,當Bitmap的大小mm(指bit數(shù))足夠大時,比如比所有可能出現(xiàn)的不重復元素個數(shù)還要大10倍以上時,錯誤概率是可以接受的。
這里有一個google實現(xiàn)的布隆過濾器,我們來看看它的誤判率:
在這個實現(xiàn)中,Bitmap的集合m、輸入的原始數(shù)集合n、哈希函數(shù)k的取值都是按照上面最優(yōu)的方案選取的,默認情況下保證誤判率ε=0.5k<0.03≈0.55,因而此時k=5。
而還有一個很有趣的地方是,實際使用的卻并不是5個哈希函數(shù)。實際進行映射時,而是分別使用了一個64bit哈希函數(shù)的高、低32bit進行循環(huán)移位。注釋中包含著這個算法的論文“Less Hashing, Same Performance: Building a Better Bloom Filter”,論文中指明其對過濾器性能沒有明顯影響。很明顯這個實現(xiàn)對于m>232時的支持并不好,因為當大于231?1的下標在算法中并不能被映射到。
海量數(shù)據(jù)問題解題思路
參考:https://blog.csdn.net/luochoudan/article/details/53736752
個人將這些題分成了兩類:一類是容易寫代碼實現(xiàn)的;另一類側重考察思路的。毫無疑問,后一種比較簡單,你只要記住它的應用場景、解決思路,并能在面試的過程中將它順利地表達出來,便能以不變應萬變。前一種,需要手寫代碼,就必須要掌握一定的技巧,常見的解法有兩種,就是前面說過的堆排和快排的變形。
- 堆排序:我認為不用變形,會原始堆排序就行。
- 快排變形(找到最大的TopK): 當len(ary) - K == key or len(ary) - K == key + 1時就得到了最大的K個數(shù)。
注意點:
- 分小文件:hash后直接存儲原來的值,而不是將hash值分到各個文件中。
- 單位換算:一字節(jié)8bit
經(jīng)典題目:
序號對應于參考網(wǎng)頁:
https://blog.csdn.net/v_july_v/article/details/6685962
hash后將海量數(shù)據(jù)分到另外的小文件中,分別處理,最后再歸并
1.2.3.4.7.8.11.13
經(jīng)典例題:2
有10個文件,每個文件1G,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重復。要求你按照query的頻度排序。
方案1:
順序讀取10個文件,按照hash(query)%10的結果將query寫入到另外10個文件(記為)中。這樣新生成的文件每個的大小大約也1G(假設hash函數(shù)是隨機的)。
找一臺內(nèi)存在2G左右的機器,依次對用hash_map(query, query_count)來統(tǒng)計每個query出現(xiàn)的次數(shù)。利用快速/堆/歸并排序按照出現(xiàn)次數(shù)進行排序。將排序好的query和對應的query_cout輸出到文件中。這樣得到了10個排好序的文件(,此處有誤,更正為b0,b1,b2,b9)。
對這10個文件進行歸并排序(內(nèi)排序與外排序相結合)。
方案2:
一般query的總量是有限的,只是重復的次數(shù)比較多而已,可能對于所有的query,一次性就可以加入到內(nèi)存了。這樣,我們就可以采用trie樹/hash_map等直接來統(tǒng)計每個query出現(xiàn)的次數(shù),然后按出現(xiàn)次數(shù)做快速/堆/歸并排序就可以了
bitmap直接映射
經(jīng)典例題:5
在2.5億個整數(shù)中找出不重復的整數(shù),內(nèi)存不足以容納這2.5億個整數(shù)。
方案1:采用2-Bitmap(每個數(shù)分配2bit,00表示不存在,01表示出現(xiàn)一次,10表示多次,11無意義)進行,共需內(nèi)存2^32*2bit=1GB內(nèi)存,還可以接受。然后掃描這2.5億個整數(shù),查看Bitmap中相對應位,如果是00變01,01變10,10保持不變。所描完事后,查看bitmap,把對應位是01的整數(shù)輸出即可。
方案2:也可采用上題類似的方法,進行劃分小文件的方法。然后在小文件中找出不重復的整數(shù),并排序。然后再進行歸并,注意去除重復的元素。
最大最小堆
經(jīng)典例題:6
海量數(shù)據(jù)分布在100臺電腦中,想個辦法高效統(tǒng)計出這批數(shù)據(jù)的TOP10。
在每臺電腦上求出TOP10,可以采用包含10個元素的堆完成(TOP10小,用最大堆,TOP10大,用最小堆)。比如求TOP10大,我們首先取前10個元素調整成最小堆,如果發(fā)現(xiàn),然后掃描后面的數(shù)據(jù),并與堆頂元素比較,如果比堆頂元素大,那么用該元素替換堆頂,然后再調整為最小堆。最后堆中的元素就是TOP10大。
桶排序
經(jīng)典例題:15
給定n個實數(shù),求著n個實數(shù)在實軸上向量2個數(shù)之間的最大差值,要求線性的時間算法。
方案1:最先想到的方法就是先對這n個數(shù)據(jù)進行排序,然后一遍掃描即可確定相鄰的最大間隙。但該方法不能滿足線性時間的要求。故采取如下方法:
并查集
經(jīng)典例題:16
TopK問題(注重代碼實現(xiàn))
經(jīng)典例題:12
100w個數(shù)中找出最大的100個數(shù)。
方案1:采用局部淘汰法。選取前100個元素,并排序,記為序列L。然后一次掃描剩余的元素x,與排好序的100個元素中最小的元素比,如果比這個最小的要大,那么把這個最小的元素刪除,并把x利用插入排序的思想,插入到序列L中。依次循環(huán),知道掃描了所有的元素。復雜度為O(100w*100)。
方案2:采用快速排序的思想,每次分割之后只考慮比軸大的一部分,知道比軸大的一部分在比100多的時候,采用傳統(tǒng)排序算法排序,取前100個。復雜度為O(100w100)。
方案3:在前面的題中,我們已經(jīng)提到了,用一個含100個元素的最小堆完成。復雜度為O(100wlg100)。
字典樹Tire樹
經(jīng)典例題:3.9.10
有一個1G大小的一個文件,里面每一行是一個詞,詞的大小不超過16字節(jié),內(nèi)存限制大小是1M。返回頻數(shù)最高的100個詞。
方案1:順序讀文件中,對于每個詞x,取,然后按照該值存到5000個小文件(記為)中。這樣每個文件大概是200k左右。如果其中的有的文件超過了1M大小,還可以按照類似的方法繼續(xù)往下分,直到分解得到的小文件的大小都不超過1M。對每個小文件,統(tǒng)計每個文件中出現(xiàn)的詞以及相應的頻率(可以采用trie樹/hash_map等),并取出出現(xiàn)頻率最大的100個詞(可以用含100個結點的最小堆),并把100詞及相應的頻率存入文件,這樣又得到了5000個文件。下一步就是把這5000個文件進行歸并(類似與歸并排序)的過程了。
求中位數(shù)
經(jīng)典例題:14
一共有N個機器,每個機器上有N個數(shù)。每個機器最多存O(N)個數(shù)并對它們操作。如何找到N^2個數(shù)中的中數(shù)?
方案1:先大體估計一下這些數(shù)的范圍,比如這里假設這些數(shù)都是32位無符號整數(shù)(共有232個)。我們把0到232-1的整數(shù)劃分為N個范圍段,每個段包含(232)/N個整數(shù)。比如,第一個段位0到232/N-1,第二段為(232)/N到(232)/N-1,…,第N個段為(232)(N-1)/N到232-1。然后,掃描每個機器上的N個數(shù),把屬于第一個區(qū)段的數(shù)放到第一個機器上,屬于第二個區(qū)段的數(shù)放到第二個機器上,…,屬于第N個區(qū)段的數(shù)放到第N個機器上。注意這個過程每個機器上存儲的數(shù)應該是O(N)的。下面我們依次統(tǒng)計每個機器上數(shù)的個數(shù),一次累加,直到找到第k個機器,在該機器上累加的數(shù)大于或等于(N2)/2,而在第k-1個機器上的累加數(shù)小于(N2)/2,并把這個數(shù)記為x。那么我們要找的中位數(shù)在第k個機器中,排在第(N2)/2-x位。然后我們對第k個機器的數(shù)排序,并找出第(N2)/2-x個數(shù),即為所求的中位數(shù)的復雜度是O(N^2)的。
方案2:先對每臺機器上的數(shù)進行排序。排好序后,我們采用歸并排序的思想,將這N個機器上的數(shù)歸并起來得到最終的排序。找到第(N2)/2個便是所求。復雜度是O(N2*lgN^2)的。
補充題目:在10G的數(shù)據(jù)中找出中位數(shù)
不妨假設10G個整數(shù)是64bit的。
2G內(nèi)存可以存放256M個64bit整數(shù)。
我們可以將64bit的整數(shù)空間平均分成256M個取值范圍,用2G的內(nèi)存對每個取值范圍內(nèi)出現(xiàn)整數(shù)個數(shù)進行統(tǒng)計。這樣遍歷一邊10G整數(shù)后,我們便知道中數(shù)在那個范圍內(nèi)出現(xiàn),以及這個范圍內(nèi)總共出現(xiàn)了多少個整數(shù)。
如果中數(shù)所在范圍出現(xiàn)的整數(shù)比較少,我們就可以對這個范圍內(nèi)的整數(shù)進行排序,找到中數(shù)。如果這個范圍內(nèi)出現(xiàn)的整數(shù)比較多,我們還可以采用同樣的方法將此范圍再次分成多個更小的范圍(256M=2^28,所以最多需要3次就可以將此范圍縮小到1,也就找到了中數(shù))。
補充樹的知識:
AVL樹
最早的平衡二叉樹之一。應用相對其他數(shù)據(jù)結構比較少。windows對進程地址空間的管理用到了avl樹。
紅黑樹
平衡二叉樹,廣泛用在c++的stl中。如map和set都是用紅黑樹實現(xiàn)的。
b/b+樹
用在磁盤文件組織 數(shù)據(jù)索引和數(shù)據(jù)庫索引。
trie樹(字典樹):
用在統(tǒng)計和排序大量字符串,如自動機。
參考:
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并發(fā)知識點快速復習手冊(上)
- Java并發(fā)知識點快速復習手冊(下)
- Java虛擬機知識點快速復習手冊(上)
- Java虛擬機知識點快速復習手冊(下)
- 快速梳理23種常用的設計模式
- Redis基礎知識點面試手冊
- Leetcode題解分類匯總(前150題)
- 面試常問的小算法總結
- 查找算法總結及其部分算法實現(xiàn)Python/Java
- 排序算法實現(xiàn)與總結Python/Java
- HTTP應知應會知識點復習手冊(上)
- HTTP應知應會知識點復習手冊(下)
- 計算機網(wǎng)絡基礎知識點快速復習手冊
- …等(請查看全復習手冊導航)
關注我
我是蠻三刀把刀,目前為后臺開發(fā)工程師。主要關注后臺開發(fā),網(wǎng)絡安全,Python爬蟲等技術。
來微信和我聊聊:yangzd1102
Github:https://github.com/qqxx6661
原創(chuàng)博客主要內(nèi)容
- 筆試面試復習知識點手冊
- Leetcode算法題解析(前150題)
- 劍指offer算法題解析
- Python爬蟲相關技術分析和實戰(zhàn)
- 后臺開發(fā)相關技術分析和實戰(zhàn)
同步更新以下博客
1. Csdn
http://blog.csdn.net/qqxx6661
擁有專欄:
- Leetcode題解(Java/Python)
- Python爬蟲實戰(zhàn)
- Java程序員知識點復習手冊
2. 知乎
https://www.zhihu.com/people/yang-zhen-dong-1/
擁有專欄:
- Java程序員面試復習手冊
- LeetCode算法題詳解與代碼實現(xiàn)
- 后臺開發(fā)實戰(zhàn)
3. 掘金
https://juejin.im/user/5b48015ce51d45191462ba55
4. 簡書
https://www.jianshu.com/u/b5f225ca2376
個人公眾號:Rude3Knife
如果文章對你有幫助,不妨收藏起來并轉發(fā)給您的朋友們~
總結
以上是生活随笔為你收集整理的海量数据处理问题知识点复习手册的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021-技能大赛-信息安全管理与评估-
- 下一篇: python文本分类汇总_用Python