一、 海量數據,出現次數最多or前K
1、給A,B兩個文件,各存放50億條URL,每條URL佔用64個字節,內存限制爲4G,找出A,B中相同的URL。
【分析】我們先來看如果要把這些URL全部加載到內存中,需要多大的空間。
1MB = 2^20 = 10^6 = 100W
1GB = 2^30 = 10^9 = 10億
50億 = 5G * 64 Byte = 320G
明顯是不可能全部加載到內存中的。我們可採用以下方法解決:
方法1:
採用Bloom filter,假設布隆過濾器的錯誤率爲0.01,則位數組大小m約爲輸入元素個數n的13倍,此時需要的哈希函數k約爲8個。
元素個數:n = 5G
位數組大小:m = 5G * 13 = 65G = 650億 即需要650億個bit位才能達到錯誤率0.01
而我們擁有的內存可容納bit位個數:4G * 8bit = 32G bit = 320億,按此實現錯誤率大於0.01。
方法2:
分別掃描A,B兩個文件,根據hash(url)%k(k爲正整數,比如k = 1000,那麼每個小文件只佔用300M,內存完全可以放得下)將url劃分到不同的k個文件中,比如a0,a1,....a999;b0,b1,...b999;這樣處理後相同的url肯定在對應的小文件中(a0 vs b0,a1 vs b1,...a999 vs b999)因爲相同的url%1000的值肯定相同,不對應的小文件不可能有相同的url;然後我們只要求出1000對小文件中相同的url即可。比如對於a0 vs b0,我們可以遍歷a0,將其中的url存放到hash_map中,然後遍歷b0,如果b0中的某個url在hash_map中,則說明此url在a和b中同時存在,保存下來即可。
1)a,b分別用hash分成m個小文件
2)在a對應第i個文件,用hash表標記url是否出現,遍歷在b對應的第i個文件查看url在hash表中是否存在,若存在則爲共同url
3)合併m個文件中找到的共同url
2、 海量日誌數據,提取出某日訪問百度次數最多的那個IP。
IP有32位,共有232232個IP。
1)採用hash的方式,ip%m,將大文件分成m個小文件。
2)對每個小文件,用hash表統計ip出現的次數。找出這個小文件出現次數最多的ip
3)在這m個ip中,比較得到出現次數最多的ip。
如果是top k的話,就維護一個長度爲k的最小堆。
3、統計最熱門的10個查詢串,要求使用的內存不能超過1G。
假設目前有一千萬個記錄,這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。每個查詢串的長度爲1-255字節。一個查詢串的重複度越高,說明查詢它的用戶越多,也就是越熱門。
300萬*255=7.65x10^8<1GB
1)用hash表統計查詢串出現的頻率
2)維護長度爲k的最小堆
4、有10個文件,每個文件1G,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重複。要求你按照query的頻度排序。
10文件順序讀取,然後hash,分散到10個文件裏面去。再hash表統計詞頻,排序。最後歸併。
二、 海量數據,不重複or重複的數據
1、2.5億個整數中找出不重複的整數的個數
32位整數共有232232個,每個數用1bit標記是否出現,共需要232bit=4G/8=512M232bit=4G/8=512M
申請512M的內存,每一bit,0表示未出現,1表示已出現。
計數器count初始化爲0。
遍歷數據文件,對每一個數,查看對應標誌位,如果爲0,則count+1,並標記爲1;
2、2.5億個整數中找出不重複的整數
2-Bitmap,每個數用2個bit來標記,00未出現,01出現1次,10出現多次,11無意義。需要1G內存。
遍歷數據文件,對每個數查看標誌位,爲00則改爲01,爲01則改爲10
最後,查看bitmap輸出標誌位01的數。
3、5億個int找它們的中位數
思路是先分治,再用雙堆法:
首先我們將int劃分爲2^16個區域,然後讀取數據統計落到各個區域裏的數的個數,之後我們根據統計結果就可以判斷中位數落到那個區域。然後第二次掃描我們只統計落在這個區域中的那些數就可以了。
雙堆法的思路:
序列中的元素,前一半存儲在一個最大堆中,後一半存儲在一個最小堆中。控制MaxHeap與MinHeap的大小差不能超過1。
參考:
https://www.cnblogs.com/chenhuan001/p/5866916.html
https://blog.csdn.net/my_lovely_lemon_tree/article/details/78195957