題目描述:
有一個 1GB 大小的文件,文件里面每一行是一個詞,每個詞的大小不超過 16B,內存大小限制是 1MB,要求返回頻數最高的 100 個詞。
分析與解答:
由於文件大小為 1GB,而內存大小只有 1MB,因此不可能一次把所有的詞讀入到內存中處理,需要采用分治的方法,把一個大的文件分解成多個小的子文件,從而保證每個文件的大小都小於 1MB,進而可以直接被讀取到內存中處理。具體的思路如下:
1)遍歷文件。對遍歷到的每一個詞,執行如下 hash 操作:hash(x)%2000,將結果為 i 的詞存放到文件 ai 中,通過這個分解步驟,可以使每個子文件的大小為 400KB 左右。如果這個操作后某個文件的大小超過 1MB 了,那么就可以采用相同的方法對這個文件繼續分解,直到文件的大小小於 1MB 為止。
2)統計出每個文件中出現頻率最高的 100 個詞。最簡單的方法為,使用 hash_map 來實現,具體實現方法:遍歷文件中的所有詞,對於遍歷到的詞,如果在 hash_map 中不存在,那么把這個詞存入 hash_map 中(鍵為這個詞,值為 1),如果這個詞在 hash_map 中已經存在了,那么把這個詞對應的值加 1。遍歷完后可以非常容易地找出出現頻率最高的 100 個詞。
3)第 2)步找出了每個文件出現頻率最高的 100 個詞,這一步可以通過維護一個小頂堆來找出所有詞中出現頻率最高的 100 個。具體方法:遍歷第一個文件,把第一個文件中出現頻率最高的 100 個詞構建成一個小頂堆(如果第一個文件中詞的個數小於 100,可以繼續遍歷第二個文件,直到構建好有 100 個結點的小頂堆為止)。繼續遍歷,如果遍歷到的詞的出現次數大於堆頂上詞的出現次數,可以用新遍歷到的詞替換堆頂的詞,然后重新調整這個堆為小頂堆。當遍歷完所有文件后,這個小頂堆中的詞就是出現頻率最高的 100 個詞。當然這一步也可以采用類似歸並排序的方法把所有文件中出現頻率最高的 100 個詞排序,最終找出出現頻率最高的 100 個詞。
引申:怎么在海量數據中找出重復次數最多的一個?
前面的算法是求解 top100,而這道題目只是求解 top1,可以使用同樣的思路來求解。唯一不同的是,在求解出每個文件中出現次數最多的數據后,接下來從各個文件中出現次數最多的數據中找出出現次數最多的數,不需要使用小頂堆,只需要使用一個變量就可以完成。方法很簡單,此處不再贅述。