347. 前 K 个高频元素
1.题目描述
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
示例 2:
说明:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
2.方法1(桶排序)
首先使用哈希表统计数组元素的频率,统计完成后,创建一个二维数组,将频率作为数组第一个维度的下标,将元素作为第二个维度的值,当出现不同的元素频率相同时,直接添加到第二个维度即可。倒序遍历二维数组,区前K个高频元素。
3.代码
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> m;
for(auto & num : nums){
m[num]++;
}
//二维数组第一维下标是数字出现的频率
vector<vector<int>> buckets(nums.size()+1);
for(auto iter = m.begin();iter != m.end();++iter){
buckets[iter->second].push_back(iter->first);//元素频率作为下标,元素作为值,如果两个元素的频率相同,则加入数组第二维
}
vector<int> res(k);
int count = 0;//记录是第几高的频率
//将buckets前k个高频元素放入res中
for(int i = buckets.size() - 1;i >= 0;--i){
for(int j = 0;j < buckets[i].size();++j){//取出每个频率的元素
res[count] = buckets[i][j];
if(++count == k){
return res;
}
}
}
return res;
}
};
4.复杂度分析
时间复杂度:O(n),n 表示数组的长度。首先,遍历一遍数组统计元素的频率,这一系列操作的时间复杂度是 O(n);桶的数量为 n + 1,所以桶排序的时间复杂度为 O(n);因此,总的时间复杂度是 O(n)。
空间复杂度:O(n)
5.方法2(快速选择)
用哈希表保存数组每个元素出现的频率,把元素和相应的频率构造成pair<int,int>保存到vector中,对vector进行倒序排序,排序标准时元素的频率。把第K高的频率移动到正确的位置,则K之前的元素的频率都大于第K个元素的频率,把这部分元素存入结果数组res中。
6.代码
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> m;
for(auto &num : nums){
m[num]++;
}
vector<pair<int,int>> data(m.begin(),m.end());
int left= 0;
int right = data.size()-1;
int index = partiton(data,left,right);
while(index != k-1){
if(index > k-1){
right = index - 1;
}
else{
left = index + 1;
}
index = partiton(data,left,right);
}
vector<int> res;
for(int i = 0;i < k;++i){
res.push_back(data[i].first);
}
return res;
}
int partiton(vector<pair<int,int>>& nums,int left,int right){
int t = left;
for(int i = left;i < right;++i){
if(nums[i].second > nums[right].second){
swap(nums[t++],nums[i]);
}
}
swap(nums[t],nums[right]);
return t;
}
};
7.复杂度分析
时间复杂度:O(n)
空间复杂度:O(n)