Given a non-empty array of integers, return the k most frequent elements.
For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].
原文:https://leetcode.com/problems/top-k-frequent-elements/description/
题中给定一个数组,需要统计这些数字各个出现的频率,并且返回频率最高的K个。
如果但是统计频率的话,使用hash表就能够简单的解决,但是现在需要考虑的问题是如何找出频率最高的K个,可以很容易想到桶排序,创建一个数组作为桶,然后该数组的下标对应数字的频率,数组本身元素存放的是这个频率对应的数字本身。比如:[1,1,2,4,4,4],这个数组中1出现了两次,2出现了一次,4出现了三次,所以作为桶的数组应该这样排列:[0,2,1,4,0],0代表没有出现,也就是桶中元素代表数字,下标代表频率。
然而可能会出现频率一样的情况,假设数组为:[1,1,2,2,3],就会出现1和2对应的频率相同的情况。所以不能够简单的使用数组进行存放,而是需要考虑到频率相同的情况,问题就转换为如何处理相同数字散列的问题。明白了问题所在,就需要解决问题,这里可以使用嵌套数组来解决,如果有频率相同的情况,只需要将这些相同频率的内容放在一个数组中然后在放进桶中即可。这样既可以保证桶数组的下标仍然是频率,同样也能够记录下所有频率相同的数字。
最后从后往前找出K个数字即可。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
if(!nums.size() || nums.size()==k) return nums;
unordered_map<int,int> frequentMap;// 用来统计每个元素出现的频率
for(int i=0;i<nums.size();i++)
frequentMap[nums[i]]++;// 进行统计
vector<vector<int>> bucket(nums.size()+1);// 创建一个桶
for(auto kv : frequentMap) {// 遍历统计数据
bucket[kv.second].push_back(kv.first);// 将其放入桶中
}
vector<int> result;
for(int i=bucket.size()-1;i>=0;i--) {
for(int j=0;j<bucket[i].size();j++){
if(!k) return result;// 如果已经找出了所有的K个,则直接返回
result.push_back(bucket[i][j]);
k--;
}
}
return result;
}
};
还可以利用优先队列的特性来做,将数字的频率和数字本身存放队列中,队列默认的是数字大的优先级高,我们使用pair时,会根据pair.first的数字来进行排序,所以将pair.first设置为数字的频率,pair.second设置为数字本身。然后队列优先级最高的K个就是频率最高的,找出其对应的数字即可。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
if(!nums.size() || nums.size()==k) return nums;
unordered_map<int,int> frequentMap;// 用来统计频率
for(int i=0;i<nums.size();i++)
frequentMap[nums[i]]++;// 进行统计
vector<int> result;
priority_queue<pair<int,int>> pq;
for(auto kv : frequentMap) {
pq.push(make_pair(kv.second,kv.first));
}
while(!pq.empty() && k--) {
result.push_back(pq.top().second);
pq.pop();
}
return result;
}
};