資料結構::一些經典的大資料題

海綿寶寶的歐尼發表於2017-02-22

前言:

1、說明:一般解決大資料問題有兩個思路:

1)先將與這道題相關的所有的資料結構進行使用一遍,如果有合適的就直接進行使用

2)如果不能直接使用,一般就要進行雜湊切分,然後再使用合適的資料結構進行問題的解決

2、在這裡我先來介紹一種常用於大資料問題的方法:雜湊切分
1)先估算出要切分的大小

2)然後使用雜湊的除留餘數法進行各個資料的對映

經典題:

1、給一個超過100G大小的log file,log中存在著IP地址,設計演算法找到出現此數最多的IP地址 

思路分析:

1)要進行雜湊切分編號,log file可以看做是字串,利用雜湊字串轉換演算法進行轉換,轉換成整型後,利用雜湊函式進行對映,同一IP地址肯定對映到同一編號中,

2)這裡我們使用效率很快的雜湊表,進行此數的統計,就可以找出出現此數最多的IP地址

2、與上題條件相同,如何找到topK的IP地址

思路分析:

1)要找到topK的IP地址,我們如果直接進行排序的話,那麼有兩個問題,第一就是記憶體放不下,第二就是效率太慢

2)所以這我們可以建一個K大小的堆,那麼建什麼堆呢,這裡建小堆比較好,因為來一個數和進行堆頂的元素進行比較,然後進行向下調整,大的就下去了,因此最終統計的就是topK
3、給定100億個整數,設計演算法找到只出現一次的整數

思路分析:

1)100億個數,無符號整型最多才42億多,因此我們首先要明白,這裡有很多重複的數,所以我們在進行空間的建立時,只用分析42億多的就可以了,那麼就是16G,這道題沒有規定要使用多大的記憶體,但是如果我們直接建16G的,那也不可能,所以我們就利用點陣圖來進行解決,那麼整型是需要32位的,就需要大約500M的記憶體就可以了

2)然後我們就可以進行遍歷只出現一次的整數
4、給兩個檔案,分別有100億個整數,我們只有1G記憶體,如何找到兩個檔案的交集

思路分析:

1)檔案進行比較,用點陣圖顯然不能解決

2)肯定要進行雜湊切分,我們將兩個檔案分別切分為1000個檔案,先對檔案A分的1000個檔案裡的整數進行雜湊分配,即取出來整數模除1000,使相同的整出進入相同的檔案,檔案B切分的1000個檔案進行同樣的處理,然後分別拿A雜湊切分好的第一個檔案和B雜湊切分好的第一個檔案對比,找出交集存到一個新檔案中,依次類推,直到2000個檔案互相比較完。

5、1個檔案有100億個int,1G記憶體,設計演算法找到出現次數不超過2次的整數

思路分析:

1)這裡類似於第三題

2)但是要找出現次數不超過2次的整數,我們可以將狀態點陣圖的位用兩位,因為我們就表示三種狀態,在,不在,重複。
6、給兩個檔案,分別有100億個query,我們只有1G記憶體,如何找到兩個檔案的交集?分別給出精確演算法和近似演算法

@精確演算法:

思路分析:

1)我們首先來看,100億個query(一般query就當做字串),如果我們假定這裡的一個字串大小是50,那麼我們就需要500G大的記憶體,顯然放不下,所以我們就要進行雜湊切分

2)這裡我將它切分成1000份,那麼每份的大小就是500M,

3)然後我們使用什麼方法來進行這道題的具體解決呢,我來用圖示說明下:


@近似演算法:

利用布隆過濾器:

經過雜湊切分後,將其中一個放到雜湊表中然後讓B來進行比對

7、如何擴充套件BloomFilter使得它支援刪除元素的操作

思路分析:

1)首先我們知道

      *布隆過濾對於不存在的數是能進行準確判斷的,但是對於存在的數是不一定,因為會出現誤判的情況

      *由於布隆的特點,因此它在實現的時候,是有多個置位的,因此不同的數(或者是其它的型別)會出現置位的衝突,所以如果直接進行刪除的話,就會影響其它的數


2)因此,這裡我們可以想到一種解決辦法就是利用引用計數
8、如何擴充套件BlooFilter使得它支援計數操作?

思路分析:

1)上題中我們知道引用計數可以使得布隆過濾器實現刪除操作,但是有問題,如果我們使用引用計數的話,至少得4個位元組,而我們知道布隆過濾器的優點有節省空間,這樣的話,就有點違背了,所以我們就放棄點陣圖,所以這裡我們呢就要考慮使用樣的什麼資料結構

2)(以字串來為例)這裡我們依然用vector來儲存引用計數,然後進行雜湊字串轉換演算法進行轉換,讓轉換後對應的整型數作為下標自增,這裡很明顯就不用點陣圖了,利用引用計數已經完成了它的功能。

3)所以我們進行刪除的時候,就將計數中大於等於1的進行減減復位
9、給上千個檔案,每個檔案大小為1K-100M。給n個詞,設計演算法對每個詞找到所有包含它的檔案,你只有100K記憶體

思路分析:

1)注:檔案不能進行切分

2)//給定的記憶體很小,我們將比如說90K大小的直接利用雜湊表進行做,

   * 用一個檔案info 準備用來儲存n個詞和包含其的檔案資訊。
   * 首先把n個詞分成x份。對每一份用生成一個布隆過濾器(因為對n個詞只生成一個布隆過濾器,記憶體可能不夠用)。把生成的所有布隆過濾器存入外存的一個檔案Filter中。
   *將記憶體分為兩塊緩衝區,一塊用於每次讀入一個布隆過濾器,一個用於讀檔案(讀檔案這個緩衝區使用相當於有界生產者消費者問題模型來實現同步),大檔案可以分為更小的檔案,但需要儲存大檔案的標示資訊(如這個小檔案是哪個大檔案的)。
   *對讀入的每一個單詞用記憶體中的布隆過濾器來判斷是否包含這個值,如果不包含,從Filter檔案中讀取下一個布隆過濾器到記憶體,直到包含或遍歷完所有布隆過濾器。如果包含,更新info 檔案。直到處理完所有資料。刪除Filter檔案。

備註:
1:關於布隆過濾器:其實就是一張用來儲存字串hash值的BitMap.
2:可能還有一些細節問題,如重複的字串導致的重複計算等要考慮一下。
10、有一個字典,包含N個英文單詞,現在任意給一個字串,設計演算法找到包含這個字串的所有英文單詞。

思路分析:

1)這裡可以用kmp演算法或者字典樹

相關文章