题目描述
- 题目
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
-
示例
-
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
-
示例 2:
输入: nums = [1], k = 1 输出: [1]
-
提示:
-
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
-
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
-
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
-
你可以按任意顺序返回答案。
解题
优先队列版本
思路
-
在遍历nums数组的过程中通过map[]的特性记录nums中元素出现的频率
-
将map中的元素插入到优先队列中(键值互换的方式),
补充:priority_queue底层通过堆的方式实现(默认大根堆) -
取优先队列的前K个元素将其键值对的second放入返回数组中
-
过程图解
代码实现
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int,int> map;
for(auto& e:nums){
map[e]++;
}
priority_queue<pair<int,int>> q;
vector<int> ret;
for(auto& e:map){
q.push(make_pair(e.second,e.first));
}
for(int i=0;i<k;i++){
ret.push_back(q.top().second);
q.pop();
}
return ret;
}
};
lambda版本
思路
- 遍历整个数组并记录每个数出现的次数(频率)
- 将元素与其出现频率存储到一个vector<pair<int,int>> 中,并且根据其second值(频率)对vector中的内容进行排序
由于该排序过程存储的是键值对,并且是对键值对中的value进行排序,所以需要用lambda表达式进行操作
- 经过排序后,我们可以将排序后的键值对中的key值压入返回数组中
- 过程图示
代码实现
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> map;//用于存储频率
for(auto& e:nums){
//遍历数组记录元素出现的频率
map[e]++;
}
vector<pair<int,int>> v;
//存储记录的的元素和对应频率,用于排序
for(auto& e:map){
v.push_back(e);
}
sort(v.begin(),v.end(),[](pair<int,int>& a,pair<int,int>&b)->bool{
return a.second>b.second;
});
//对vector数组总的v进行排序
vector<int> ret;
for(int i=0;i<k;i++){
ret.push_back(v[i].first);
}
return ret;
}
};
- 总结:
该问题的解决需要根据其频率大小来进行排序,并将排序后的前k元素频率递减的顺序将元素放到返回数组中
而排序的方式我这里只展示了两种
- 1.使用优先队列的方式(priority_queue)
- 2.使用lambda表达式的方式
这类问题在统计出现频率的时候使用map/unordered_map 通过其特殊的[] 操作来统计,(其他方式暂时没用过)