题目
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
思路:首先遍历整个数组,并用哈希表记录每个数值出现的次数,再用优先队列,根据数值出现的次数进行排序(构建大根堆)。最后依次取k次堆顶元素
class Solution {
public:struct cmp{bool operator()(const pair<int,int>& p1,const pair<int,int>& p2){return p1.first<p2.first;}};vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int,int> mNum;priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> PrioQue;vector<int> ret;for(auto e:nums){mNum[e]++;}for(auto e:mNum){PrioQue.push({e.second,e.first});}for(int i=0;i<k;i++){ret.push_back(PrioQue.top().second);PrioQue.pop();}return ret;}
};
时间复杂度会是O(nlogn),n为nums数组大小
思路二:维护一个size=k的小根堆,时间复杂度会是O(nlogk)
在这里,可以建立一个小顶堆,然后遍历「出现次数数组」:
如果堆的元素个数小于 k,就可以直接插入堆中。
如果堆的元素个数等于 k,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 k个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中。
遍历完成后,堆中的元素就代表了「出现次数数组」中前 k大的值。
class Solution {
public:static bool cmp(pair<int, int>& m, pair<int, int>& n) {return m.second > n.second;}vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int, int> occurrences;for (auto& v : nums) {occurrences[v]++;}// pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);for (auto& [num, count] : occurrences) {if (q.size() == k) {if (q.top().second < count) {q.pop();q.emplace(num, count);}} else {q.emplace(num, count);}}vector<int> ret;while (!q.empty()) {ret.emplace_back(q.top().first);q.pop();}return ret;}
};
优先级队列自定义排序
c++优先队列priority_queue(自定义比较函数)_c++ priority_queue自定义比较函数_菊头蝙蝠的博客-CSDN博客
在写题时用了lambda表达式定义priority_deque第三个参数但会报错,本人的错误写法:
auto cmp=[](vector<int>&a,vector<int>&b)->bool{return a[0]>b[0];};
priority_queue<vector<int>,vector<vector<int>>,cmp> q;//小顶堆
后来查了其他资料发现写法有误,正确写法如下:
auto cmp=[](vector<int>&a,vector<int>&b)->bool{return a[0]>b[0];};
priority_queue<vector<int>,vector<vector<int>>,decltype(cmp)> q(cmp);//小顶堆
以后还是直接用struct重载函数吧。