347. Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
Note:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
题目链接:https://leetcode-cn.com/problems/top-k-frequent-elements/
思路
总体的思路是:先统计,再排序,输出。
法一:排序算法
时间复杂度O(nlogn):
统计:O(n)。hash表查找O(1),++操作O(1),共n个元素。
排序:排序最低复杂度O(nlogn)。
扫描二维码关注公众号,回复:
9440658 查看本文章
输出:O(n)。
这是通常思路,可以看出瓶颈在排序算法这里。
这个实现就不写了。
法二:优先队列维护k个元素
在统计好之后,使用优先队列维护k个元素,若新频率比队列中最小频率大时,弹出最小,插入新频率。
调整新插入元素的位置:O(logk),故算法时间复杂度为O(nlogk),当k<<n时有较大提升。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
if(nums.size()<=0 || k<=0) return res;
unordered_map<int,int> freq;
for(int num: nums){
++freq[num];
}
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> que;
for(unordered_map<int,int>::iterator it=freq.begin(); it!=freq.end(); ++it){
if(que.size()<k) que.push(make_pair(it->second, it->first));
else{
auto tmp = que.top();
if(tmp.first<it->second){
que.pop();
que.push(make_pair(it->second, it->first));
}
}
}
while(!que.empty()){
res.push_back(que.top().second);
que.pop();
}
return res;
}
};
法三:优先队列维护(n-k)个元素
优先队列不维护topk大的,改去维护剩下较小的元素,因此只要是被从队列被挤出来/挤不进的元素,就可以直接输出。
法二在n和k差不多大时没啥提升,而本法在这种情况下能有很好的优化效果。
注意:(n-k)不一定为正数,<=0时都是输出所有数据。这点需要在弹出队列时加一个判断。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
if(nums.size()<=0 || k<=0) return res;
unordered_map<int,int> freq;
for(int num: nums){
++freq[num];
}
priority_queue<pair<int,int>, vector<pair<int,int>>, less<pair<int,int>>> que;
int len = freq.size()-k;
for(unordered_map<int,int>::iterator it=freq.begin(); it!=freq.end(); ++it){
if(que.size()<len) que.push(make_pair(it->second, it->first));
else{
if(que.empty()) res.push_back(it->first);
else{
auto tmp = que.top();
if(tmp.first>it->second){
res.push_back(tmp.second);
que.pop();
que.push(make_pair(it->second, it->first));
}else res.push_back(it->first);
}
}
}
return res;
}
};