维护一个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]。输出堆即可。
题目:给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
输入: 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;
}
输出: