力扣347. 前 K 个高频元素
题目来源(力扣):
https://leetcode.cn/problems/top-k-frequent-elements/description/
题目描述:
找到一个数组中前k个出现频率高的数。
1 <= nums.length <= 10^5
k 的取值范围是 [1, 数组中不相同的元素的个数]
基本思路:
最直观的方式就是记录数组中出现了哪些数字,以及各个数字出现的次数,最后利用排序算法例如快速排序sort一遍,打印前k个即可。
优化的方式就是,维护一个大小为k的优先队列,而非使用sort。
具体实现可以使用到map、结构体、快排等知识,这里只给出2种写法,以供参考。
写法1
哈希表+结构体快排
class Solution {
public:
struct oo{
int val;
int tot;
};
vector<oo>a; //下标从1开始便于操作
unordered_map<int,int>index;//将nums中的数字映射到a中
static bool cmp(oo X,oo Y){
return X.tot>Y.tot;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
oo tmp;
a.push_back(tmp); //从下标1开始便于操作
for(int i=0;i<nums.size();i++){
int ind=index[nums[i]];
if(ind==0){
tmp.val=nums[i];
tmp.tot=1;
index[nums[i]]=a.size();
a.push_back(tmp);
}
else {
a[ind].tot++;
}
}
sort(a.begin()+1,a.end(),cmp);
// for(int i=1;i<a.size();i++)
// cout<<a[i].val<<" : "<<a[i].tot<<endl;
vector<int>ans;
for(int i=1;i<=k;i++){
ans.push_back(a[i].val);
}
return ans;
}
};
写法2
哈希表+优先队列
参考《代码随想录》如下,
class Solution
{
public:
class cmp
{
public:
bool operator()(const pair<int, int> &A, const pair<int, int> &B)
{ //根据q.second(即元素出现的次数)的大小来制定优先队列,一定是小根堆,这样子每次弹出的才是出现频率较小数
return A.second > B.second;
}
};
unordered_map<int, int> mmp; //统计元素出现的次数
vector<int> ans;
vector<int> topKFrequent(vector<int> &nums, int k)
{
for (auto num : nums)
{
mmp[num]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q;
for (auto it = mmp.begin(); it != mmp.end(); it++)
{
q.push(*it);
if (q.size() > k)
{ // 大小为k的优先队列
q.pop();
}
}
while (q.size())
{
//cout << q.top().second << endl;
ans.push_back(q.top().first);
q.pop();
}
return ans;
}
};
时间复杂度
写法1为O(nlogn),写法2为O(nlogk) ,n为数组大小,k为数组中不同元素的个数
浙公网安备 33010602011771号