開發面試Hash面試考題


Hash部分分爲三部分講解,各位遊客可根據分類進行對應博客閱讀:

  1. 開發面試Hash原理詳解
  2. 開發面試Hash常見算法
  3. 開發面試Hash面試考題

博客書寫不易,您的點贊收藏是我前進的動力,千萬別忘記點贊、 收藏 ^ _ ^ !

1. Hash Top 查找

內容描述

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

要求

請你統計最熱門的10個查詢串,要求使用的內存不能超過1G。

分析

有兩種思路:使用排序的方案 和 使用hash的方法

1.排序法
1) 首先我們最先想到的的算法就是排序了,首先對這個日誌裏面的所有Query都進行排序,然後再遍歷排好序的Query,統計每個Query出現的次數了。

2)但是題目中有明確要求,那就是內存不能超過1G,一千萬條記錄,每條記錄是255Byte,根據255100010000/(102410241024)=2.37G大小的內存

3)當數據量比較大而且內存無法裝下的時候,我們可以採用外排序的方法來進行排序,這裏我們可以採用歸併排序,歸併排序有一個比較好的時間複雜度O(nlogn)

4)排完序之後我們再對已經有序的Query文件進行遍歷,統計每個Query出現的次數,再次寫入文件中,其時間複雜度O(n)。

5)總體時間複雜度O(n)+O(nlogn)=O(nlogn)

2.Hash Table法
對於數據的統計相比排序有更好的方案,那就是使用hash table的方式。

題目中雖然有一千萬個Query,但是由於重複度比較高,因此事實上只有300萬的Query量,其大小爲2.37*0.3=0.71G,對於1G的內存要求是滿足的。Hash Table的查找速度非常快接近O(1)。

這樣我們的算法就是:維護一個Key爲Query字串,Value爲該Query出現次數的HashTable,每次讀取一個Query,如果該字串不在Table中,那麼加入該字串,並且將Value值設爲1;如果該字串在Table中,那麼將該字串的計數加一即可。最終我們在O(n)的時間複雜度內完成了對該海量數據的處理。

比較:Hash Table相對於排序法在時間複雜度上提高了一個數量級,爲O(n)。且hash Table的方案只需要進行一次IO數據操作,在操作性上更有優勢

補充

算法:部分排序
題目要求是求出Top 10,因此我們沒有必要對所有的Query都進行排序,我們只需要維護一個10個大小的數組,初始化放入10個Query,按照每個Query的統計次數由大到小排序,然後遍歷這300萬條記錄,每讀一條記錄就和數組最後一個Query對比,如果小於這個Query,那麼繼續遍歷,否則,將數組中最後一條數據淘汰,加入當前的Query。

最後當所有的數據都遍歷完畢之後,那麼這個數組中的10個Query便是我們要找的Top10了。不難分析出,這樣,算法的最壞時間複雜度是N*K, 其中K是指top多少。

算法:堆
在部分算法二中,每次比較完成之後,需要的操作複雜度都是K,因爲要把元素插入到一個線性表之中,而且採用的是順序比較。

這裏我們注意一下,該數組是有序的,一次我們每次查找的時候可以採用二分的方法查找,這樣操作的複雜度就降到了logK,可是,隨之而來的問題就是數據移動,因爲移動數據次數增多了。不過,這個算法還是比算法二有了改進。

基於以上的分析,我們想到一種既能快速查找,又能快速移動元素的數據結構呢?回答是肯定的,那就是堆。
藉助堆結構,我們可以在log量級的時間內查找和調整/移動。因此到這裏,我們的算法可以改進爲這樣,維護一個K(該題目中是10)大小的小根堆,然後遍歷300萬的Query,分別和根元素進行對比。

與部分算法相比我們採用了最小堆這種數據結構代替數組,把查找目標元素的時間複雜度有O(K)降到了O(logK)。採用堆數據結構,最終的時間複雜度就降到了N‘logK。

總結

最優的方案是先用Hash表統計每個Query出現的次數O(N),然後用堆數據結構找出前10,時間複雜度爲N*O(logK),所以總的時間複雜度是O(N)+NO(logK)。 N=1000萬 ,N=300萬

2. SimHash應用

內容描述

如何設計一個比較兩篇文章相似度的算法?

要求

用最快最有效的方式比較兩篇文章的相似度。

分析

我們首選最容易想到的兩種方案是

  1. 一種方案是先將兩篇文章分別進行分詞,得到一系列特徵向量,然後計算特徵向量之間的距離(可以計算它們之間的歐氏距離、海明距離或者夾角餘弦等等),從而通過距離的大小來判斷兩篇文章的相似度。
  2. 另外一種方案是傳統hash,我們考慮爲每一個web文檔通過hash的方式生成一個指紋(finger print)。

比較兩種法案
+採取第一種方法,若是隻比較兩篇文章的相似性還好,但如果是海量數據呢,有着數以百萬甚至億萬的網頁,要求你計算這些網頁的相似度。你還會去計算任意兩個網頁之間的距離或夾角餘弦麼?想必你不會了。

+第二種方案中所說的傳統加密方式md5,其設計的目的是爲了讓整個分佈儘可能地均勻,但如果輸入內容一旦出現哪怕輕微的變化,hash值就會發生很大的變化。如果只改變一個文字其Hash值差別都很大不容易進行比較。
H^md5(“the cat sat on the mat”)=415542861
H^md5(“the cat sat on the mat”)=668720516

可理想當中的hash函數,需要對幾乎相同的輸入內容,產生相同或者相近的hash值,換言之,hash值的相似程度要能直接反映輸入內容的相似程度,故md5等傳統hash方法也無法滿足我們的需求。

來自於GoogleMoses Charikar發表的一篇論文“detecting near-duplicates for web crawling”中提出了simhash算法,專門用來解決億萬級別的網頁的去重任務。
具體使用極其原理請查看我的博客《開發面試Hash常見算法》

總結

使用Simhash能完美快速的解決網頁去重判斷處理。

博客書寫不易,您的點贊收藏是我前進的動力,千萬別忘記點贊、 收藏 ^ _ ^ !

相關鏈接

  1. 開發面試Hash原理詳解
  2. 開發面試Hash常見算法
  3. ART與Dalvik、JVM之間的關係你懂了嗎?
  4. 熱更新你都知道哪些?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章