大資料處理的思路一般是這樣的:把乙個記憶體中放不下的檔案按照一定的方法切分成小檔案,再看是否有合適的資料結構能解決這個問題。當然,有時候不用切分,用位圖也可以解決,根據具體問題而定。接下來我們看看下面幾道大資料的面試題,這種題一般面試官也只是需要乙個思路。
1)給乙個超過100g大小的log file, log中存著ip位址, 設計演算法找到出現次數最多的ip位址?
問題分析:
100g普通機器記憶體中肯定是放不下的,目前使用的ip位址相當於乙個32位的字串,所以,這麼大的檔案,我們考慮切分,但是僅僅切分還不行,假設有1g可用的記憶體,那我們切分成100份,那還得把這100個檔案全部遍歷一遍,把每乙個出現的ip都統計一下次數,最後找到出現次數最多的ip,這是一種解法,不過效率不高。
解決方案:
把這32位的ip通過字串雜湊函式轉化成對應的整形,把100g檔案分成1000個,從硬碟中讀取這些ip,轉化成整形後對檔案個數取餘,餘數是多少就放進哪個檔案裡,這樣就保證相同的ip一定是在同乙個檔案裡。這種方法也叫做hash分桶法。分好之後去統計每個檔案裡出現次數最多的,問題就轉化成找這1000個ip出現次數最多的乙個。
(2)與上題條件相同,如何找到top k的ip?
問題分析:
上一題是找出現次數最多的1個,這個是最多的前k個,很容易想到的是像剛才一樣,找出每個檔案裡次數最多的,出來再找前k個,然而這樣實際上是不對的。為啥呢?因為不能保證某個檔案裡的最大的就一定比另乙個檔案裡最小的大。比如檔案1裡出現次數最多是10次,而檔案2裡出現次數最少的是100次。
解決方案:
跟第一題一樣先採用hash分桶法分好,然後找出每個檔案裡的top k,最後top k 進行彙總。如何找出top k 呢?這裡完全可以考慮建立乙個k個資料的小堆,最後堆裡保留的就是k個最大的數,為啥要建立小堆?正常想著不是應該建立大堆嗎?可以參考我之前寫的關於堆的部落格,最後有說到:
(3)給定100億個整數,設計演算法找到只出現一次的整數。
問題分析:
首先,100億整數記憶體肯定放不下,其次,整數範圍是到42億多,所以,這100億裡一定有很多重複的數字。一般首先想到的就是切分,切到記憶體中能放下,然後遍歷去找。太慢了,它找只出現一次的,可以考慮用位圖。
解決方案:
位圖一般是用1個位來表示數存在或者不存在,這裡它找只出現1次的,所以用兩個位來表示,兩個位就是4個狀態,我們只使用3個狀態就好,分別是不存在,出現1次,出現多次,具體多次我們不管,這裡只管出現1次的。用兩個位表示乙個數,42億個數大概需要開1個g大的點陣圖就ok。
(4)給兩個檔案,分別有100億個整數,我們只有1g記憶體,如何找到兩個檔案交集?
問題分析:
記憶體放不下,我們首先想到了切割,把a檔案切分成100份,拿b檔案去比對。缺點依然是慢,效率不高。
解決方案:
雜湊分桶法,100億個整數分到1000個檔案裡(一般用雜湊分桶法分的檔案數都比較多),每個數對1000取餘,放到餘數對應的檔案裡。兩個檔案都經過雜湊分桶後,只需要對比編號一致的檔案,因為雜湊分桶保證了大小相同的整數一定分到同乙個檔案裡。這樣就高效很多了。
( 5)1個檔案有100億個int,1g記憶體,設計演算法找到出現次數不超過2次的所有整數。
問題分析:
這個題和第三題很類似。不過它找的是不超過兩次的,即是出現1次和出現兩次的。
解決方案:
依然使用位圖,用兩個位來表示乙個數,四個狀態分別是:沒有出現,出現一次,出現2次,出現多次。這次我們關注的出現1次的和出現2次的。
( 6)給兩個檔案,分別有100億個query,我們只有1g記憶體,如何找到兩個檔案交集?分別給出精確 演算法和近似演算法。
問題分析:
這又是乙個找交集的問題,所以可以考慮用雜湊分桶法解決,那麼近似的演算法是什麼呢?把字串轉化成整形,當乙個元素被加入集合時,通過k
個hash 函式
將這個元素對映成乙個位陣列(bit array)中的 k 個點
,把它們置為1
。檢索時,我們只要看看這些點是不是都是 1 就(大約)知道集合中有沒有它了:
畫圖示意:
解決方案:
精確演算法用雜湊分桶法,和前面的題很類似,近似的用布隆過濾器,得到的結果是近似的。
( 7)如何擴充套件bloomfilter( 布隆過濾器)使得它支援刪除元素的操作?
問題分析:
因為乙個字串是用多個位表示的,其他字串很可能與要刪除的字串占用了相同的位(如上圖),所以,不能直接刪除,影響了其他字元狀態的表示。
解決方案:
採用引用計數,不過因為字串出現的次數可能比較大,乙個char是不行的,我們用size_t,但是這樣就失去了布隆過濾器省空間的優勢,這也是沒辦法的,如果檔案太大,那就只能先進行切分了。採用引用計數就不用再拿乙個位來表示存在不存在了,直接拿引用計數來表示,為0代表不存在。我在這裡實現了乙個支援刪除的布隆。
原始碼:
#include#include#includeusing namespace std;
struct hashfunc1
return hash;
}};struct hashfunc2
return hash;
}};struct hashfunc3
return hash;
}};struct hashfunc4
else
}return hash;
}};struct hashfunc5
return hash;
}};//乙個字串型別的布隆過濾器
templateclass bloomfilter
void set(const char* str)
bool reset(const char* str) //刪除
bool test(const char* str) //查詢
protected:
vector_refbloomfilter; //為了支援刪除,直接使用乙個size_t 的vector來做引用計數
size_t _range;
};void testbloomfilter()
void set(const int& x)
void reset(const int& x)
bool test(const int& x)
private:
vector_bitmap;
};void testbitmap()
這是我對於大資料問題的一些看法,分享出來,如上述問題有更優的解決方案,請不吝賜教~ 面試題 大資料處理
1 給乙個超過100g大小的log file log中存著ip位址,設計演算法找到出現次數最多的ip位址?我們先考慮一下,100g大小的檔案,一般是無法存到普通的計算機中的,我們的硬碟根本沒這麼大 2 用檔案的前k個數建小堆 3 用k 1個數和堆頂相比,大的話替換,調整堆 3 給定100億個整數,設...
大資料處理面試題
首先看看資料重複率,若重複率很高,可以直接在記憶體中將資料存進hashmap,然後利用最大堆求出出現次數最多的k個資料。將大檔案用hash劃分為多個小檔案,如果小檔案還超出了所需記憶體怎麼辦?沒事,再對其進行hash,將其分為更多的小檔案。如果多次hash檔案大小仍然超出記憶體,就不用管它了,因為這...
大資料處理面試題
題目 解決方法 ip位址最多有232 2 32 232種取值情況,所以不能完全載入到記憶體中處理 可以考慮採用 分治 的思想,按照ip位址的hash ip 1024值,將海量ip日誌分別儲存到1024個小檔案中。這樣,每個小檔案最多包含4mb個ip位址 對於每個小檔案,可以構建乙個ip為key,出現...