面試必須掌握的十個海量數據問題及解決方案

原文鏈接:BAT直通車-海量數據專題

更多精彩內容(BAT招聘、筆試、面試、技術),請訪問BAT直通車

題目

問題一:現有海量日誌數據,要提取出某日訪問百度次數最多的那個IP(可以將題幹簡化,假設日誌中僅包含IP數據,也就是說待處理的文件中包含且僅包含全部的訪問IP,但內存空間有限,不能全部加載,假設只有512MB)

解決方案:

這是一道典型的分治思想的題目,這種問題處理起來套路比較固定,對於大部分的數據量比較大的前提的問題而言,分治都是一個可選的解決方案,但不一定是最優的,解決方法基本劃分爲三步走:

第一:如何有效的劃分數據

第二:如何在子集上解決問題

第三:如何合併結果

這裏寫圖片描述

那麼對於本問題就顯得比較明顯了:

首先解決如何劃分,由於IP地地址範圍從000.000.000.000~255.255.255.255共有2^32個大約4GB,那麼我們可以通過取模的方式進行劃分,直接將四段數據相連就得到一個IP對應的數字A,再對A模1024(模數取多少可以自己指定,保證每個小文件能被放到內存就好),這樣大文件被劃分成小文件了,並且相同的IP一定被劃分到相同的文件中。

其次解決每個小文件中TOP1的問題:
這裏可以用很多方式進行處理,比如你可以構造自己的HashMap,key爲IP,value爲當前出現次數,最後找到value最大的Key即爲當前文件中出現次數最多的IP。

最後要解決結果合併問題:

這裏直接將1024個子文件的統計結果進行比較就好,不用排序,直接選擇最大的一個就好。

注意:這裏第二步是影響效率的地方,讀者可以想想如何優化這裏的Wordcount,可以用trie樹等


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

解決方案:細心的讀者可以發現這個和第一個問題應該沒有太大別,區別就在於第一個問題是Top1,這個問題是TOP100。

那麼對於這個問題,主要考慮的是如何劃分(每個文件要小於1M),這裏可以考慮劃分爲2028份。

對於第二步可以考慮用堆排序
即常用的TopN手段。

第三部就是更爲常見的歸併排序


問題三:給定a、b兩個文件,各存放50億個url,每個url各佔64字節,內存限制是4G,讓你找出a、b文件共同的url?

解決方案:這種題目,我首先想到的就是布隆過濾器(BloomFilter)
當然使用布隆過濾器存在一定的錯誤率,所以面試者可以和面試官進行進一步的溝通,看是否允許有一定的錯誤率。

如果使用布隆過濾器,那麼問題就很好辦了,4G的內存足以容納300多億的bit,所以足夠處理了,先將a文件中的url都放入布隆過濾器,之後遍歷b文件,對每個url都詢問布隆過濾器看其是否已經存在,如果存在,則此條URL輸入結果文件。

關於布隆過濾器使用空間和錯誤率的關係可以看這篇博文

第二種方案就是採用更爲通用的但對於這個問題效率較低的分治思想,對a,b進行分片,a,b文件大小都大約320G,那麼每個文件都切分成1G的320個小文件。

lista->{a1,a2,a3...a320}

listb->{b1,b2,b3...b320}

僞代碼如下:

resultlist = []
for tmpfile in lista:
    for infile in listb:
        for url in tmpfile:
            if url in infile:
                resultlist.add(url)

當然這個在實現的時候可以進一步優化,首先可以並行處理(這裏只用了2G內存,所以至少可以2個線程並行)

其次,可以對a中URL進行小部分判重處理,如果之前已經有了,
就不必處理。


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

解決方案:這種題又是典型的wordcount問題,首先這種題不用說都是內存有限制(最好問問面試官,內存限制是多少)。如果沒內存限制直接一個trie樹就搞定了(因爲一般來說query的重複都比較多)。

如果內存限制比較大,那麼可以嘗試屢試不爽的分治方法。但在使用之前需要先對原來的文件進行一下處理通過hash(url)%A,這裏A只分成多少分,這裏可以也取10,就是將原來的10個文件轉爲新的10個文件,如果內存限制比較大,那麼這個A可以根據內存大小調整,要讓1G/A <= 內存大小。

接下來就是要對每個小文件進行統計,可以用hashmap(url,count),也可以用trie樹。

之後採用歸併排序的方法得到最終結果。


問題五:怎麼在海量數據中找出重複次數最多的一個?

解決方案:如果看了前面四個題目,這裏相信讀者應該已經會自己解決了。

使用屢試不爽的分治思路,先劃分成小文件,之後分別統計,之後再選取max,讀者可以思考如何優化小文件內的處理方法。


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

解決方案:首先對於這種問題基本上都可以採用分治的思想,先進行劃分後進行單獨處理,最後進行結果合併。但對於這道題目顯然分治思想比較牽強,效率不高。

那麼再審視一下這個題目,其只需要找到不重複的整數,無需什麼排序,而且又限定在整數,那麼顯然可以考慮位集的思想。
2.5億個整數,顯然可以用一個250M的位集表示。

一個位集可以表示如下:

但簡單的位集只能表示存在與否,因爲每個bit表示一個整數,1個bit只能表示兩種情況,但在本題目中不但需要表示存在性,還需要表示是否多次出現,即需要尋找出現次數>=2,那麼至少需要兩個bit才能表示這種情況,00->不出現,01->出現一次,10->出現至少2次,這樣就能統計出那些數據出現重複。

總結一下就是本題目可以用位集的變形,每個數用2個bit表示,那麼總共需要250M*2b = 500Mb的內存,完全滿足題目,而且效率還是o(n)。


問題七:一個文本文件,大約有一萬行,每行一個詞,要求統計出其中最頻繁出現的前10個詞,請給出思想,給出時間複雜度分析。

解決方案:分治思想這裏就簡要闡述一下,可以利用trie樹進行詞頻統計,之後採用TopN的解決方法,關於排序的問題可以看這篇博文

堆排序的時間複雜度是n(longk),n是數據集合大小,k是topK中的k,那麼複雜度是max(n*len(e),nlogk),其中len(e)表示字符串平均大小。

這裏想講一下另一種稍顯技巧的方法,即用變形的位集表示,由於題目中只有1w的數據,那麼一個詞最多出現1w詞,那麼用18個bit就可以表示最多出現的次數,說道這裏讀者可以回顧一下第六個題目了,其實和題目六很相似的,這裏每個數字用18個bit表示,那麼剩下的問題就是解決如何將每個詞轉化爲1~10000的數字,這裏讀者可以自行YY或者自行搜索,方法有很多。關鍵的問題是要想到可以用這種方式來解決,那麼複雜度顯然就是o(n)


問題八:給40億個不重複的unsigned int的整數,沒排過序的,然後再給一個數,如何快速判斷這個數是否在那40億個數當中?
(PS:騰訊面試題)

解決方案:這個題目限定的比較明確了,整數、不重複,那麼理所當然可以用bitMap的思想去解決了。

申請一個40億的bit數組,初始化爲0,遍歷數據集合,有的佔位1,給定待驗證的數據,直接看相應位置的是1還是0即可。

當然有人可能覺得40億的bit內存裝不下啊,那怎麼辦,當然可以分治了,寫到N個文件中總可以了吧,根據待驗證的數,直接查找相應的文件,在相應的文件中查看是1還是0。

比如分成1W份,被分割的文件按下標存儲:

file1,file2,file3 ... file10000

那麼相當於每個文件存儲4Mb的位,待驗證的數據爲a,那麼目標文件的index爲

index*400000<=a<=(index+1)*400000

求出index,再在file(index)中查找。


問題九:上千萬或上億數據(有重複),統計其中出現次數最多的前N個數據。

解決方案:典型的TopN問題,請參考前面的問答題。


問題十: 搜索引擎會通過日誌文件把用戶每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度爲1-255字節。假設目前有一千萬個記錄(這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。一個查詢串的重複度越高,說明查詢它的用戶越多,也就是越熱門),請統計出最熱門的10個查詢串,要求使用的內存不能超過1G。

解決方案:典型的TopN問題,請參考前面的問題的答案,可以考慮使用分治的思想。


總結:處理海量數據問題的四板斧

1.分治

基本上處理海量數據的問題,分治思想都是能夠解決的,只不過一般情況下不會是最優方案,但可以作爲一個baseline,可以逐漸優化子問題來達到一個較優解。傳統的歸併排序就是分治思想,涉及到大量無法加載到內存的文件、排序等問題都可以用這個方法解決。

適用場景:數據量大無法加載到內存

技能鏈接:歸併排序


2.哈希(Hash)


個人感覺Hash是最爲粗暴的一種方式,但粗暴卻高效,唯一的缺點是耗內存,需要將數據全部載入內存。

適用場景:快速查找,需要總數據量可以放入內存


3.bit(位集或BitMap)

位集這種思想其實簡約而不簡單,有很多擴展和技巧。比如多位表示一個數據(能夠表示存在和數量問題),BloomFilter(布隆過濾器就是一個典型的擴展),在實際工作中應用場景很多,比如消息過濾等,讀者需要掌握,但對於布隆過濾器使用有一些誤區和不清楚的地方,讀者可以看下面這篇博客避免這些性能上的誤區。

適用場景:可進行數據的快速查找,判重

技能鏈接:布隆過濾器使用的性能誤區


4.堆(Heap)

堆排序是一種比較通用的TopN問題解決方案,能夠滿足絕大部分的求最值的問題,讀者需要掌握堆的基本操作和思想。

適用場景:處理海量數據中TopN的問題(最大或最小),要求N不大,使得堆可以放入內存

技能鏈接:排序算法-Heap排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章