数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
1 <= nums.length <= 105
k
的取值范围是 [1, 数组中不相同的元素的个数]
k
个高频元素的集合是唯一的**进阶:**你所设计算法的时间复杂度 必须 优于 O(n log n)
,其中 n
是数组大小。
算法思路:
本题的关键是要找到数组中出现频率最高的K个元素。一个直观的思路是使用哈希表记录每个元素出现的次数,然后对记录的次数进行排序,取出次数最多的K个元素即可。
具体步骤是:
具体实现:
这里的关键点是compare函数指定了排序规则,并且sort后的vec并不是我们直接要的结果,而是需要从中提取出top k的first元素。
class Solution {
public:
static bool compare(const pair<int,int>& v1,const pair<int,int>& v2){
return v1.second > v2.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int,int> nums_map;
vector<int> result;
vector<pair<int,int>> vec;
for(int i = 0; i < nums.size(); i++){
nums_map[nums[i]]++;
}
for(auto it = nums_map.begin(); it != nums_map.end(); it++){
vec.push_back(make_pair(it->first,it->second));
}
sort(vec.begin(), vec.end(), compare);
for(int i = 0; i < k; i++) {
result.push_back(vec[i].first);
}
return result;
}
};
算法分析:
这个算法的核心思路是利用哈希表统计元素频率,并维护一个大小为 K 的最小堆,final结果储存在最小堆里。具体步骤如下:
最小堆的排序规则通过自定义 compare 函数实现。
class Solution {
public:
static bool compare(const pair<int,int>& v1,const pair<int,int>& v2){
return v1.second > v2.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int,int> nums_map;
for(int i = 0; i < nums.size(); i++){
nums_map[nums[i]]++;
}
priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(&compare)> pri_que(compare);//建立最小优先队列
for(map<int,int>::iterator it = nums_map.begin();it != nums_map.end();it++){
pri_que.push(*it);
if(pri_que.size() > k){
pri_que.pop();
}
}
//写入结果数组
vector<int> result(k);
for(int i = k-1; i >= 0; i--){
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};
方法二里优先队列的声明是:
priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(&compare)> pri_que(compare);
这个语句中:
priority_queue
表示声明一个优先队列, vector>
指定了优先队列的模板参数,第一个是元素类型,第二个是底层容器类型decltype(&compare)
是比较函数的类型>
表示模板参数列表结束pri_que
是优先队列的变量名(compare)
是以比较函数作为参数构造优先队列而pri_que(compare)
则表示以 compare 函数为参数构造这个优先队列,将排序规则传入。