LeetCode 347. 前 K 个高频元素
1 题目描述
- 题目链接:347. 前 K 个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例1:
[maybe_some_pic_here]
输入: nums = [1,1,1,2,2,3], k = 2
输出: 【1,2]
示例2:
输入: nums = [1], k = 1
输出: [1]
2 思路
- 通过哈希进行频率计数,然后转换为
vector
并按频率进行降序排序,然后输出频率最高的k
个数字即可。但是这种方法的复杂度为O(nlogn)
,不满足题意。 - 采用堆排序的方法,同样采用哈希计数,然后按出现频率建立小顶堆(堆的大小为
k
),然后输出堆即可。
- 自己造轮子版
class Solution {
/* 建堆并维持堆的性质 */
void heapify(vector<pair<int, int>>& vec, int size, int index) {
int smallest = index;
int lson = index * 2 + 1, rson = index * 2 + 2;
if(lson < size && vec[lson].first < vec[smallest].first) {
smallest = lson;
}
if(rson < size && vec[rson].first < vec[smallest].first) {
smallest = rson;
}
if(index != smallest) {
auto tmp = vec[index];
vec[index] = vec[smallest];
vec[smallest] = tmp;
heapify(vec, size, smallest);
}
}
/* 这里和堆排序相差就是少了后边的将首个元素与末尾元素交换 */
void heapSort(vector<pair<int, int>>& vec, int size) {
for(int i = (size -1)/2; i >= 0; i--) {
heapify(vec, size, i);
}
}
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> m;
for(int i: nums) {
m[i]++; // 频率计数
}
vector<pair<int, int>> vec(k, {0, 0});
for(auto &[num, cnt]: m) {
//printf("%d %d\n", num, cnt);
if(cnt > vec[0].first) {
vec[0] = make_pair(cnt, num);
heapSort(vec, k); // 维护大小为k的小顶堆
}
}
vector<int> ret(k);
for(int i = 0; i < k; ++i) {
ret[i] = vec[i].second;
//cout << vec[i].first << " "<< vec[i].second<< endl;
}
return ret;
}
};
STL
库版-1
/* 自定义比较函数 */
struct cmp{
bool operator()(pair<int, int>& a, pair<int, int>& b){
return a.second > b.second;
}
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> m;
for(int i: nums) m[i]++;
priority_queue<pair<int, int>, vector<pair<int,int>>, cmp> pq;
for(auto &[num, cnt]: m) {
if(pq.size() == k) {
if(cnt < pq.top().second) continue;
pq.pop();
}
pq.push({num, cnt});
}
vector<int> ret;
while(!pq.empty()) {
ret.emplace_back((pq.top()).first);
pq.pop();
}
return ret;
}
};
STL
库版-2
/* 自定义数据类型 */
struct node{
int cnt;
int num;
node(int num_, int cnt_): num(num_), cnt(cnt_){};
/* 重写operator <,一般不重写operator > */
friend bool operator < (node a, node b){
return a.cnt > b.cnt;
}
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> m;
for(int i: nums) m[i]++; // 频率计数
priority_queue<node> pq; // 比较方式缺省,默认调用operator <
for(auto &[num, cnt]: m) {
if(pq.size() == k) {
if(cnt < pq.top().cnt) continue; // 当前的数频率更高,插入堆中
pq.pop();
}
pq.push(node(num, cnt));
}
vector<int> ret;
while(!pq.empty()) {
ret.emplace_back((pq.top()).num);
pq.pop();
}
return ret;
}
};