1、题目:前K个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
2、解题思路
前K个最大元素的问题,是非常常见的问题,用大根堆或者小根堆来做。堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
此题要求前 k 个最大的元素,应该用小根堆吗,在元素一个一个加入堆中,把最小的元素给弹出,这样剩下来的就是最大的元素了。
关于priority_queue,去看小知识。
3、代码
// 时间复杂度:O(nlogk)
// 空间复杂度:O(n)
class Solution
{
public:
// 小顶堆
class mycomparison
{
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k)
{
// 要统计元素出现频率
unordered_map<int, int> map; // map<nums[i],对应出现的次数>
for (int i = 0; i < nums.size(); i++)
{
map[nums[i]]++;
}
// 对频率排序
// 定义一个小顶堆,大小为k
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
// 用固定大小为k的小顶堆,扫面所有频率的数值
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++)
{
pri_que.push(*it);
if (pri_que.size() > k)
{ // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
pri_que.pop();
}
}
// 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
vector<int> result(k);
for (int i = k - 1; i >= 0; i--)
{
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};