目录
- LeetCode 347:前 K 个高频元素
-
- 题目描述
- 解题
-
- 哈希+排序
- 哈希+优先队列
LeetCode 347:前 K 个高频元素
题目描述
给定一个非空的整数数组,返回其中出现频率前 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 是数组的大小。bunengpai
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。
解题
哈希+排序
最直接的思路应该是对整个数组进行排序,这样相同的数字相邻,可以很轻松的统计每个数字出现的次数,但是算法要求复杂度优于 O ( n l o g n ) O(nlogn) O(nlogn),所以直接排序是不可行的。但还是要统计每个整数的频率,不能排序,那么可以借助哈希表,这样不用考虑数值范围和各种取值可能。统计好之后按照次数再排序即可。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> nums_counts;
for (auto &i : nums)
++nums_counts[i];
vector<pair<int,int>> nums_counts_sort(nums_counts.begin(), nums_counts.end());
sort(nums_counts_sort.begin(), nums_counts_sort.end(), [](pair<int, int> &a, pair<int, int> &b) { return a.second > b.second; });
vector<int> topKF_nums(k, 0);
for (int i=0; i < k; ++i)
topKF_nums[i] = nums_counts_sort[i].first;
return topKF_nums;
}
};
哈希+优先队列
思路与哈希+排序本质是一致的,只不过借助优先队列来排序和控制选择的数目,优先队列按照统计数从小到大存储<统计数-数字>这一数对。统计好数字出现的次数之后,对哈希表进行遍历,如果优先队列的大小小于k,则不断将<统计数-数字>压入队列中,如果优先队列大小等于k,且队列顶部元素统计数小于当前元素统计数,则将顶部元素弹出,将该元素压入队列;如果队列顶部元素统计数不小于当前元素统计数,则继续向前迭代。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> nums_counts;
for (auto &i : nums)
++nums_counts[i];
priority_queue< pair<int,int>, vector<pair<int, int>>, greater< pair<int,int> > > pq;
for (auto &p : nums_counts){
if (pq.size()==k){
if (pq.top().first < p.second){
pq.pop();
pq.push(make_pair(p.second, p.first));
}
}
else
pq.push(make_pair(p.second, p.first));
}
vector<int> topKF_nums(k, 0);
while (k){
topKF_nums[--k] = pq.top().second;
pq.pop();
}
return topKF_nums;
}
};