347. 前 K 个高频元素

维护一个size是k的堆。

求前k大的数,用小根堆

求前k小的数,用大根堆

求前k大,当堆的size<k时,直接将数push进堆里,当堆的size>k时,去掉堆顶,最终堆中的数据就是最后的答案。

如数组arr={1,7,6,8,3,13,4,9},求最大的前3个数(一般来说求前k大/小,数组中数是很大的,直接用排序,在选择前k大/小的话,效率不高)。

首先创建堆,其size=0,一直push知道size=3时,此时小根堆的数据是[1, 7, 6],堆顶为1,数组的下一个数8,大于堆顶(如果小于堆顶则不进堆,因为堆中的所有元素都比其大),故push进堆里,push(8),小根堆为[1, 7, 6, 8],此时堆的size=4>k=3,去掉对顶,去掉堆顶是用最后一个数取代堆顶,再调整堆,所以此时的堆为[6, 7, 8],一直重复这样的操作,知道遍历完数组,最后小根堆的数据为[8,13, 9]。输出堆即可。

题目:给定一个非空的整数数组,返回其中出现频率前 高的元素。

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

题目是求出现频率前k高的元素,维护一个size是k的小根堆,按照出现频率来创堆。

可以自定义堆的排序,两种方法,一是重载运算符"<"。二是重写仿函数。

using myPair = pair<int, int>; //第一个数存的是数组中的值,第二个是出现频率
class cmp  //仿函数
{
public:
	bool operator()(const myPair&p1, const myPair& p2)
	{
		return p1.second > p2.second;
	}
};

对于此题,先用字典对保存数组中的数字出现的频率,key值为数组中的元素,value是key出现的频率。再根据频率来创建堆

#include<iostream>
#include<vector>
#include<queue>
#include<unordered_map>
using namespace std;

using myPair = pair<int, int>;
class cmp //重写仿函数
{
public:
	bool operator()(const myPair&p1, const myPair& p2)
	{
		return p1.second > p2.second;
	}
};

class Solution
{
public:
	vector<int> topKFrequent(const vector<int>& nums, int k)
	{
		unordered_map<int, int> m;
		for (auto n : nums)
			++m[n];
		priority_queue<myPair,vector<myPair>,cmp> minHeap;
		for (auto i : m)
		{
			//cout << i.first << " " << i.second << endl;
			myPair temp = make_pair(i.first, i.second);
			if (minHeap.size() < k)
				minHeap.push(temp);
			else
			{
				minHeap.push(temp);
				minHeap.pop();
			}
		}
		vector<int> res;
		while (!minHeap.empty())
		{
			res.push_back(minHeap.top().first);
			minHeap.pop();
		}
		return res;
	}
};

int main()
{
	Solution soultion;
	vector<int> v = {1,1,1,2,2,3};
	int k = 2;
	for (auto i : soultion.topKFrequent(v, k))
		cout << i << " ";
	cout << endl;
	system("pause");
	return 0;
}

输出:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值