lc.347 统计前K个高频元素
题目:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
https://leetcode-cn.com/problems/top-k-frequent-elements/
解法一:优先队列+小根堆
//一种小根堆思路
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
unordered_map<int, int> m; //map不用pair,前一个为值,后一个为频率
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; //小根堆
for(auto& i : nums)
{
m[i]++;
}
for(auto& i : m)
{
q.emplace(i.second, i.first); //q.emplace(i.first, i.second)不对,不明白
if(q.size() > k)
q.pop();
}
while(!q.empty())
{
res.push_back(q.top().second); //q.top().first不对,不明白
q.pop();
}
return res;
}
};
//另一种小根堆思路
class Solution{
public:
//自己定义大小比较方法
class Mycomparison{
public:
bool operator()(const pair<int ,int>& a, const pair<int, int>& b)//重载
{
return a.second > b.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
unordered_map<int, int> m; //map不用pair
priority_queue<pair<int, int>, vector<pair<int, int>>, Mycomparison> q;
for(auto& i : nums)
{
m[i]++;
}
for(auto& i : m)
{
q.emplace(i);
if(q.size() > k)
q.pop();
}
while(!q.empty())
{
res.push_back(q.top().first);
q.pop();
}
return res;
}
};
解法二:遍历寻找
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
unordered_map<int, int> m; //map不用pair
for(auto& i : nums)
{
m[i]++;
}
// vector<int> v;
int maxfreq = 0;
for(unordered_map<int, int>:: iterator it = m.begin(); it != m.end(); it++)
{
if(it->second > maxfreq)
maxfreq = it->second;
}
while(k)
{
for(auto& i : m)
{
if(i.second == maxfreq)
{
res.push_back(i.first);
k--;
}
}
maxfreq--;
}
return res;
}
};
解法三:桶排序
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
unordered_map<int, int> m;
for(auto& i : nums)
{
m[i]++;
}
int maxfreq = 0;
for(auto& i : m)
{
if(i.second > maxfreq)
maxfreq = i.second;
}
vector<vector<int>> temp(maxfreq+1);//为什么不用数组:考虑到相同频率的元素,使用数组会覆盖。注意要+1以对齐下标和频率
for(unordered_map<int, int>:: iterator it = m.begin(); it != m.end(); it++)
{
temp[it->second].push_back(it->first);
}
for(int t = maxfreq; res.size() < k && t >= 0; t--)
{
for(auto& i : temp[t])
{
res.push_back(i);
}
if(res.size() == k)
break;
}
return res;
}
};
注意要点:
1.求频率相关考虑用map。
2.求前k个大考虑到用小根堆,前k小考虑用大根堆。这样做的好处是当插入元素比堆顶小/大时,可以直接扔掉,节约内存。
3.priority_queue默认为大根堆,可以自定义判断方式。