找出一个字符串中出现次数最多的字_海量数据中找出前k大数(topk问题)
在海量數據中找出出現頻率最好的前k個數,或者從海量數據中找出最大的前k個數,這類問題通常被稱為top K問題。
針對top K類問題,通常比較好的方案是分治+Trie樹/hash+小頂堆(就是上面提到的最小堆),即先將數據集按照Hash方法分解成多個小數據集,然后使用Trie樹或者Hash統計每個小數據集中的query詞頻,之后用小頂堆求出每個數據集中出現頻率最高的前K個數,最后在所有top K中求出最終的top K。
方法進階:
1、最簡單的方法就是快排,取topk
2、局部淘汰法。用一個容器保存前k個數,然后將剩余的所有數字——與容器內的最小數字相比,如果所有后續的元素都比容器內的k個數還小,那么容器內這k個數就是最大k個數。如果某一后續元素比容器內最小數字大,則刪掉容器內最小元素,并將該元素插入容器,最后遍歷完所有的數,得到的結果容器中保存的數即為最終結果了
3、分治法。將1億個數據分成100份,每份100萬個數據,找到每份數據中最大的10000個,最后在剩下的100*10000個數據里面找出最大的10000個。100萬個數據里面查找最大的10000個數據的方法如下:用快速排序的方法,將數據分為2堆,如果大的那堆個數N大于10000個,繼續對大堆快速排序一次分成2堆,如果大的那堆個數N大于10000個,繼續對大堆快速排序一次分成2堆,如果大堆個數N小于10000個,就在小的那堆里面快速排序一次,找第10000-n大的數字;遞歸以上過程,就可以找到第1w大的數。參考上面的找出第1w大數字,就可以類似的方法找到前10000大數字了。此種方法需要每次的內存空間為10^6*4=4MB,一共需要101次這樣的比較。
4、采用最小堆。首先讀入前10000個數來創建大小為10000的最小堆,建堆的時間復雜度為O(mlogm)(m為數組的大小即為10000),然后遍歷后續的數字,并于堆頂(最小)數字進行比較。如果比最小的數小,則繼續讀取后續數字;如果比堆頂數字大,則替換堆頂元素并重新調整堆為最小堆。整個過程直至1億個數全部遍歷完為止。然后按照中序遍歷的方式輸出當前堆中的所有10000個數字。該算法的時間復雜度為O(nmlogm),空間復雜度是10000(常數)。
以下是一些經常被提及的該類問題。
(1)有10000000個記錄,這些查詢串的重復度比較高,如果除去重復后,不超過3000000個。一個查詢串的重復度越高,說明查詢它的用戶越多,也就是越熱門。請統計最熱門的10個查詢串,要求使用的內存不能超過1GB。
(2)有10個文件,每個文件1GB,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重復。按照query的頻度排序。
(3)有一個1GB大小的文件,里面的每一行是一個詞,詞的大小不超過16個字節,內存限制大小是1MB。返回頻數最高的100個詞。
(4)提取某日訪問網站次數最多的那個IP。
(5)10億個整數找出重復次數最多的100個整數。
(6)搜索的輸入信息是一個字符串,統計300萬條輸入信息中最熱門的前10條,每次輸入的一個字符串為不超過255B,內存使用只有1GB。
(7)有1000萬個身份證號以及他們對應的數據,身份證號可能重復,找出出現次數最多的身份證號。
最小堆
對于每個非葉子節點的數值,一定不大于孩子節點的數值。這樣可用含有K個節點的最小堆來保存K個目前的最大值(當然根節點是其中的最小數值)。每次有數據輸入的時候可以先與根節點比較。若不大于根節點,則舍棄;否則用新數值替換根節點數值。并進行最小堆的調整。
Python 小頂堆:
class solution:def topk(self, inputs, k):import heapqif inputs == None or len(inputs) < k or len(inputs) <= 0 or k <= 0:# 注意極限條件的確定return []output = []for number in inputs:if len(output) < k:output.append(number)else:output = heapq.nlargest(k, output)print(output)if number >= output[-1]:output[-1] = numberelse:continuereturn output 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的找出一个字符串中出现次数最多的字_海量数据中找出前k大数(topk问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微粒贷利率如何下调
- 下一篇: 银行卡丢了别人能干嘛