问题描述 :
给定一个非空的整数数组,返回其中出现频率前 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数组的长度n,
然后输入n个整数,以空格分隔。
最后输入k。
输出说明 :
首先输出频率最高的元素,如果频率相同,则先输出元素值较大的元素。
元素之间以空格分隔。
输入范例 :
8
1 1 1 2 2 3 3 4
3
输出范例 :
1 3 2
思路:
1.使用map来存储每个元素出现的频率
2.维护一个最小堆,最小堆中最多添加k个元素,最小堆中的元素为pair<频率,元素>。
当最小堆中不足k个元素时直接将元素加入堆
当最小堆中有k个元素时,比较堆顶元素与当前元素的频率大小,如果当前元素的频率大于堆顶元素频率,堆顶元素出队,当前元素入队
3.将堆中各个pair的second加入一个vector中,最后逆置vector就得到了结果。
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include <map>
using namespace std;
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int,int> m;
//构造元素-频率映射map
for(int i = 0; i < nums.size(); i++) {
m[nums[i]]++;
}
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> pq;
for(map<int,int>::iterator it = m.begin(); it != m.end(); it++) {
if(pq.size() == k) {
if(it->second > pq.top().first) {
pq.pop();
pq.push(make_pair(it->second,it->first));
}
}
else {
pq.push(make_pair(it->second,it->first));
}
}
vector<int> res;
while(!pq.empty()) {
res.push_back(pq.top().second);
pq.pop();
}
reverse(res.begin(),res.end()); //逆置res,使之符合题目要求
return res;
}
};
int main(void) {
int n,k,data;
cin>>n;
vector<int> nums;
for(int i = 0; i < n; i++) {
cin>>data;
nums.push_back(data);
}
cin>>k;
Solution s;
vector<int> res = s.topKFrequent(nums,k);
for(int i = 0; i < res.size(); i++) {
if(i != res.size()-1) {
cout<<res[i]<<" ";
}
else {
cout<<res[i];
}
}
return 0;
}