一、题目描述
二、解题思路
使用优先队列,设置为小根堆
- 首先用
map
记录数据出现的频度 - 维护一个大小为
K
的小根堆 - 遍历
map
,若当前遍历到的map
元素的出现频度小于小根堆堆顶元素,即若该元素的出现频度比当前小根堆最小的还小,丢弃不管,否则将小根堆堆顶元素pop
掉,将该元素压入堆,再调整堆
三、解题代码
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> counter;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int,int>> > Heap;
for(auto e: nums)
counter[e]++; //对map的随机访问
for(auto &x: counter){
auto pr = make_pair(x.second, x.first);
if(Heap.size() == k){
if(pr < Heap.top()) continue;
else Heap.pop();
}
Heap.push(move(pr)); //不进行数据拷贝,只将内存控制权转移
}
vector<int> sln(Heap.size());
k = sln.size();
while(!Heap.empty()){
sln[--k] = Heap.top().second;
Heap.pop();
}
return sln;
}
};
四、运行结果
四、题目总结
- 如果求前K次高频的元素,要用小根堆:你能不能考进前十名,不取决于你是不是比第一名分高,而取决于你能否比当前前十名里分数最低的第十名分数高
- 如果求前K次低频的元素,要用大根堆:你能不能考进倒数前十名,不取决于你是不是比第一名分低,而取决于你能否比当前倒数前十名里分数最高的倒数第十名分数低