一個較好的方法:先拿出10000個建立小根堆,對於剩下的元素,如果大於堆頂元素的值,刪除堆頂元素,再進行插入操作,否則直接跳過,這樣知道所有元素遍歷完,堆中的10000個就是最大的10000個。時間復雜度: m + (n-1)logm = O(nlogm)
優化的方法:可以把所有10億個數據分組存放,比如分別放在1000個文件中(如果是字符串hash(x)%M)。對每個文件,建立大小為10000的小根堆,然后按有序數組的合並合並起來,取出最大的10000個即是答案。
top K問題
在大規模數據處理中,經常會遇到的一類問題:在海量數據中找出出現頻率最好的前k個數,或者從海量數據中找出最大的前k個數,這類問題通常被稱為top K問題。例如,在搜索引擎中,統計搜索最熱門的10個查詢詞;在歌曲庫中統計下載最高的前10首歌等。
解決方法:針對top K類問題,通常比較好的方案是分治+Trie樹/hash+小頂堆(就是上面提到的最小堆),即先將數據集按照Hash方法分解成多個小數據集,然后使用Trie樹或者Hash統計每個小數據集中的query詞頻或頻數,之后用小頂堆求出每個數據集中出現頻率最高的前K個數,最后在所有top K中求出最終的top K。
簡陋的實現:
估計能處理1e8個整數(約400M)吧
#include<bits/stdc++.h> using namespace std; int n, k, tmp; priority_queue<int, vector<int>, greater<int>>qu; int main() { scanf("%d%d", &n, &k); for(int i = 0;i < k;i++) { scanf("%d", &tmp); qu.push(tmp); } for(int i = 0;i < n-k;i++) { scanf("%d", &tmp); if(tmp > qu.top()) { qu.pop(); qu.push(tmp); } } for(int i = 0;i < k;i++) { printf("%d ", qu.top()); qu.pop(); } return 0; }
參考鏈接: