一、题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
1 <= nums.length <= 10^5
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小
二、思路
- 第一种:使用map来统计每一个数字出现的次数,再使用一个堆来保存k个最大的次数。复杂度O(n+nlogk)
- 第二种:使用桶排序的思想,根据最大的出现次数创建多少个桶,每个桶里面放着出现该次数的数,最后倒序遍历桶即可。复杂度O(n)
三、代码
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> mp;
vector<int> ans;
for (auto val : nums) mp[val]++;
auto cmp = [](pair<int, int>& a, pair<int, int>& b){return a.second > b.second;};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);
for (auto [one, tow] : mp) {
if (q.size() == k) {
//已经有k个了进行比较 由于是小根堆比较最小的在开头
if (q.top().second < tow) {
q.pop();
q.emplace(one, tow);
}
} else {
q.emplace(one, tow);
}
}
while (!q.empty()) {
ans.push_back(q.top().first);
q.pop();
}
return ans;
}
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> mp;
vector<int> ans;
int max_size = 0;
for (auto val : nums) {
mp[val]++;
max_size = max(max_size, mp[val]);
}
vector<vector<int>> bucket(max_size + 1);
for (auto [one, tow] : mp) {
bucket[tow].push_back(one);
}
//倒序遍历桶
for (int i = max_size; i >= 1 && ans.size() < k; i--) {
for (auto val : bucket[i]) {
ans.push_back(val);
if (ans.size() == k) break;
}
}
return ans;
}
};