一、問題描述:
尋找熱門查詢: 搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串 的長度為1-255位元組。假設目前有一千萬個記錄, 這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個 。乙個查詢串的重複度越高,說明查詢它的使用者越多, 也就是越熱門。請你統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。
(1)請描述你解決這個問題的思路;
(2)請給出主要的處理流程,演算法,以及演算法的複雜度。
必備知識:
什麼是雜湊表?
雜湊表(hash table,也叫雜湊表),是根據關鍵碼值(key value)而直接進行訪問的資料結構。
也就是說,它通過把關鍵碼值對映到表中乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。
雜湊表的做法其實很簡單,就是把key通過乙個固定的演算法函式既所謂的雜湊函式轉換成乙個整型數字,然後就將該數字對陣列長度進行取餘,取餘結果就當作陣列的下標,將value儲存在以該數字為下標的陣列空間裡。
而當使用雜湊表進行查詢的時候,就是再次使用雜湊函式將key轉換為對應的陣列下標,並定位到該空間獲取value,如此一來,就可以充分利用到陣列的定位效能進行資料定位。
二、問題求解
要統計最熱門查詢,首先就是要統計每個query出現的次數,然後根據統計結果,找出top 10。所以我們可以基於這個思路分兩步來設計該演算法。
雖然有一千萬個query,但是由於重複度比較高,因此事實上只有300萬的query,每個query255byte,因此我們可以考慮把他們都放進記憶體中去,而現在只是需要乙個合適的資料結構,在這裡,hash table絕對是我們優先的選擇,因為hash table的查詢速度非常的快,幾乎是o(1)的時間複雜度。所以我們放棄分而治之/hash對映的步驟,直接上hash統計,然後排序。
步驟如下:
(1)hash統計:先對這批海量資料預處理(維護乙個key為query字串,value為該query出
現次數的hashtable,即hash_map(query,value),每次讀取乙個query,如果該字串不
在table中,那麼加入該字串,並且將value值設為1;如果該字串在table中,那麼將該字串
的計數加一即可。最終我們在o(n)的時間複雜度內用hash表完成了統計;
(2)堆排序:第二步、借助堆這個資料結構,找出top k,時間複雜度為n'logk。即借助堆結
構,我們可以在log量級的時間內查詢和調整/移動。因此,維護乙個k(該題目中是10)大小的
小根堆,然後遍歷300萬的query,分別和根元素進行對比。所以,我們最終的時間複雜度是:
o(n) + n'*o(logk),(n為1000萬,n』為300萬)。
堆排序思路:
「維護k個元素的最小堆,即用容量為k的最小堆儲存最先遍歷到的k個數,並假設它們即是最大的k個數,建堆費時o(k),並調整堆(費時o(logk))後,有k1>k2>…kmin(kmin設為小頂堆中最小元素)。繼續遍歷數列,每次遍歷乙個元素x,與堆頂元素比較,若x>kmin,則更新堆(x入堆,用時logk),否則不更新堆。這樣下來,總費時o(k*logk+(n-k)*logk)=o(n*logk)
。此方法得益於在堆中,查詢等各項操作時間複雜度均為logk。
redis做熱門查詢
redis 對於排行榜的需求,redis有乙個資料結構非常適合做這件事,那就是有序集合 sorted set redis的有序集合相關命令有序集合和集合一樣可以儲存字串,另外有序集合的成員可以關聯乙個分數 score 這個分數用於集合排序。下面以投票為例說明常見的命令,vote activity是有...
盧鬆鬆 如何查詢部落格熱門話題
在我看來,寫部落格是一件頭疼的事,如果想要有大量訪問者與回頭客必須不斷更新內容,堅持更新部落格實際上是乙個大量的工作。只要堅持更新部落格半年以後你就會深有體會。如何查詢部落格的熱門話題是乙個頭疼的問題,那麼本文就將討論使用一些工具來尋找熱門話題。知乎問答 在知乎尋找話題也是個不錯的辦法,因為在知乎有...
003 10TopK搜尋引擎熱門查詢統計
題目描述 搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1 255位元組。假設目前有一千萬個記錄 這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就是越熱門。請你統計最熱門的10個查...