題目:解決方法:
ip位址最多有232
2^32
232種取值情況,所以不能完全載入到記憶體中處理
可以考慮採用「分治」的思想,按照ip位址的hash(ip)%1024值,將海量ip日誌分別儲存到1024個小檔案中。這樣,每個小檔案最多包含4mb個ip位址
對於每個小檔案,可以構建乙個ip為key,出現次數為value的hash map,同時記錄當前出現次數最多的那個ip位址
可以得到1024個小檔案中的出現次數最多的ip,再依據常規的排序演算法得到總體上出現次數最多的ip
關於topk的補充知識看第二部分
題目:
搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255位元組。假設目前有一千萬個記錄(這些查詢串的重複度比較高,雖然總數是一千萬,但如果去掉重複後,不超過三百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就越是熱門),請統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。
解決方法:
先對這批資料進行預處理,在o(n)時間內用hash表完成統計
借助堆這個結構,找出top k,時間複雜度為nlogk
題目:
有乙個1g大小的乙個檔案,裡面每一行是乙個詞,詞的大小不超過16位元組,記憶體限制大小是1m。返回頻數最高的100個詞。
解決方法:
順序讀取檔案,對於每個詞x,取hash(x)%5000,然後按照該值存到5000個小檔案中,這樣每個檔案大概是200k左右。(注意如果其中有的檔案超過了1m大小,還可以按照類似的方法繼續往下分,直到分解得到的小檔案的大小都不超過1m。)
對每個小檔案,統計每個檔案**現的詞以及相應的頻率(可以使用trie樹/雜湊表),並取出出現頻率最大的100個詞(可以用含100個結點的最小堆),並把100個詞及相應的頻率存入檔案,這樣又得到了5000個檔案。下一步就是把這5000個檔案進行歸併(類似於歸併排序)的過程了。
問題:
給定a、b兩個檔案,各存放50億個url,,每個url佔64位元組,記憶體限制是4g,找出a、b檔案共同的url。
方案一:
可以估計每個檔案大小約為5g*64=320g,遠遠大於記憶體限制的4g。所以採取分治的方法。
遍歷檔案a,對每個url求取hash(url)%1000,然後根據所取得的值將url分別儲存到1000個小檔案。這樣每個小檔案的大小約為300m。
遍歷檔案b,採取和a相同的方式將url分別儲存到1000個小檔案,這樣處理後,所有可能相同的url都在對應的小檔案中,不對應的小檔案不可能有相同的url。然後我們只要求處1000對小檔案中相同的url即可。
求每對小檔案中相同的url時,可以把其中乙個小檔案的url儲存到hashset中。然後遍歷另乙個小檔案中的每個url,看其是否在剛才構建的hashset中,如果是,那麼就是相同的url,存到檔案裡面就可以了。
方案二:
如果允許有一定的錯誤率,可以使用bloom filter。
題目描述:
在2.5億個整數中找出不重複的整數(記憶體不足以容納這2.5億個整數)
方案一:
採用2-bitmap(每個數分配2bit,00表示不存在,01表示出現一次,10表示多次,11無意義)進行,共需記憶體232×
2bit
=1gb
2^\times2 bit=1gb
232×2b
it=1
gb記憶體,還可以接受。然後掃瞄這2.5億個整數,檢視bitmap中相對應位,如果是00變01,01變10,10保持不變。掃瞄完事後,檢視bitmap,把對應位是01的整數輸出即可。
方案二:
也可採用與第1題類似的方法,進行劃分小檔案的方法。然後在小檔案中找出不重複的整數,並排序。然後再進行歸併,注意去除重複的元素。
題目描述:
給40億個不重複的unsigned int的整數,沒排過序的,然後再給乙個數,如何快速判斷這個數是否在那40億個數當中?
方案一:
申請512m的記憶體,乙個bit位代表乙個unsigned int值。讀入40億個數,設定相應的bit位,讀入要查詢的數,檢視相應bit位是否為1,為1表示存在,為0表示不存在。
方案二:
我們把40億個數中的每乙個用32位的二進位制來表示,假設這40億個數開始放在乙個檔案中。
然後將這40億個數分成兩類:
並將這兩類分別寫入到兩個檔案中,其中乙個檔案中數的個數<=20億,而另乙個》=20億(這相當於折半了);這時與要查詢的數的最高位比較並接著進入相應的檔案再查詢。
再然後把這個檔案為又分成兩類:
並將這兩類分別寫入到兩個檔案中,其中乙個檔案中數的個數<=10億,而另乙個》=10億(這相當於折半了);與要查詢的數的次最高位比較並接著進入相應的檔案再查詢。
…以此類推,就可以找到了,而且時間複雜度為o(logn),方案2完。
問題描述:
怎麼在海量資料中找出重複次數最多的乙個?
解決思路:
先做hash,然後求模對映為小檔案,求出每個小檔案中重複次數最多的乙個,並記錄重複次數。然後找出上一步求出的資料中重複次數最多的乙個就是所求。
問題描述:
100w個數中找出最大的100個數
方案一:
可以用乙個含100個元素的最小堆完成。複雜度為o(100w*lg100)。
方案二:
採用快速排序的思想,每次分割之後只考慮比軸大的一部分,直到比軸大的一部分在比100多的時候,採用傳統排序演算法排序,取前100個。複雜度為:o(100w*100)。
方案三:
採用區域性淘汰的思想,選取前100個元素,並排序,記為序列l。然後一次掃瞄剩餘的元素x,與排好序的100個元素中最小的元素比,如果比這個最小的要大,那麼把這個最小的元素刪除,並把x利用插入排序的思想,插入到序列l中。依次迴圈,知道掃瞄了所有的元素。複雜度為o(100w*100)。
問題描述:
搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255位元組。
假設目前有一千萬個記錄(這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就是越熱門。),請你統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。
問題解析:
要統計最熱門查詢,首先就是要統計每個query出現的次數,然後根據統計結果,找出top 10。所以我們可以基於這個思路分兩步來設計該演算法。
即,此問題的解決分為以下兩個步驟:
這一步又有兩種方法:
2.1.1.1 直接排序法
首先對這個日誌裡面的所有query都進行排序,然後再遍歷排好序的query,統計每個query出現的次數。
但是由於題目裡面的記憶體不能超過1g的要求,所以不能使用直接排序。
我們可以考慮外部排序(歸併排序),排序完再對已經有序的query檔案進行遍歷,統計每個query出現的次數,再次寫入檔案中
2.1.1.2 hash table法
題目中說明了,雖然有一千萬個query,但是由於重複度比較高,因此事實上只有300萬的query,每個query 255byte,因此我們可以考慮把他們都放到記憶體中去,因此hashtable是我們優先的選擇。
現在我們的演算法可以是:維護乙個key為query,value為該query出現次數的hashtable,每次讀取乙個query,如果該字串不在table中,那麼加入該字串,並且將value值設為1;如果該字串在table中,那麼將該字串的計數加一即可。
2.1.2.1 普通排序
在本題中,三百萬條記錄,用1g記憶體可以存下,排序的時間複雜度是nlogn
2.1.2.2 部分排序
題目要求是求出top10,因此我們只需要維護乙個10大小的陣列,初始化放入10個query,按照每個query的統計次數由大到小排序,然後遍歷這300萬條記錄,每讀一條記錄就和陣列最後乙個query對比,如果小於這個query,那麼繼續遍歷,否則,將陣列中最後一條資料淘汰,加入當前的query。最後當所有的資料都遍歷完後,這個陣列中的10個query就是我們要找的top 10了,這時時間複雜度是n*k,其中k是指top是多少。
在演算法二中,每次比較完後,需要的操作複雜度都是k,因為要把元素插入到乙個線性表中,而且採用的是順序比較。借助堆結構,我們可以在log量級的時間內查詢和調整/移動。因此到這裡,我們的演算法可以改進為這樣:維護乙個k(該題目中是10)大小的小根堆,然後遍歷300萬的query,分別和根元素進行對比。
這樣,採用堆資料結構,演算法三最終的時間複雜度就降到了nlogk,和演算法二比,又有了較大的改進。
參考:
面試題 大資料處理
1 給乙個超過100g大小的log file log中存著ip位址,設計演算法找到出現次數最多的ip位址?我們先考慮一下,100g大小的檔案,一般是無法存到普通的計算機中的,我們的硬碟根本沒這麼大 2 用檔案的前k個數建小堆 3 用k 1個數和堆頂相比,大的話替換,調整堆 3 給定100億個整數,設...
大資料處理面試題
首先看看資料重複率,若重複率很高,可以直接在記憶體中將資料存進hashmap,然後利用最大堆求出出現次數最多的k個資料。將大檔案用hash劃分為多個小檔案,如果小檔案還超出了所需記憶體怎麼辦?沒事,再對其進行hash,將其分為更多的小檔案。如果多次hash檔案大小仍然超出記憶體,就不用管它了,因為這...
海量資料處理面試題
海量資料處理思路分析題 1.給乙個超過100g大小的log file,log中存著ip位址,設計演算法找到出現次數最多的ip位址?解決方法 雜湊切割topk。將100g的大檔案分成1000份,根據同乙個雜湊函式hashfunc將ip對映到向對應的檔案 每個檔案的大小可以在記憶體中處理 中,相同的ip...