力扣347题:前K个高频单词
题目描述
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
输入输出样例
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
输入: nums = [1], k = 1
输出: [1]
Tips
提示:
1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
进阶:
你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
解法一,借用hash,对次数进行排序
class Solution
{
public:
vector<int>topKFrequent(vector<int>&nums,int k)
{
if(nums.empty())
{
return nums;
}
unordered_map<int,int>maps;
for(auto i:nums)
{
if(maps.count(i))
{
maps[i]++;
}
else{
maps[i]=1;
}
}
//对hash表的值进行排序,并取要求的数组
vector<int>countNum;
for(auto i:maps)
{
countNum.push_back(i.second);
}
sort(countNum.begin(),countNum.end());
int length=countNum.size();
vector<int>res;
//获取倒数几个的值
for(int i=length-1;i>=length-k;i--)
{
res.push_back(countNum[i]);
}
vector<int>resNum;
set<int>sets;
//遍历hash
for(auto i:maps)
{
for(auto j:res)
{
if(i.second==j)
{
sets.insert(i.first);
}
}
}
for(auto i:sets)
{
resNum.push_back(i);
}
return resNum;
}
};
解法2,使用优先队列+小顶堆
class Solution2
{
public:
//使用小顶堆实现,然后遍历出现次数数组
//总的时间复杂度为O(NlogN)
vector<int>topKFrequent(vector<int>&nums,int k)
{
//使用map记录元素出现的次数
unordered_map<int,int>maps;
//初始化
for(auto i:nums)
{
maps[i]++;
}
//创建优先队列的排序方式
//使用小顶堆
struct myComparsion
{
bool operator()(pair<int,int>&p1,pair<int,int>&p2)
{
return p1.second>p2.second;
}
};
//创建优先队列
priority_queue<pair<int,int>,vector<pair<int,int>>,myComparsion> que;
//将hash表中的元素传递进优先队列中
for(auto &i:maps)
{
que.push(i);
if(que.size()>k)
{
//当长度大于k时,堆中的最小值出堆
que.pop();
}
}
//获取排序后的结果
vector<int>res;
while(!que.empty())
{
res.push_back(que.top().first);
que.pop();
}
return res;
}
};
解法三,使用快速排序的思想
class Solution3
{
public:
//使用快速排序的方法
//平均时间复杂度为O(N)
//将数组arr[l..r]做快速排序,
//将数组划分成两个部分arr[i..q-1]与arr[q+1...j],并使得arr[i..q-1]中的每一个值都不超过arr[q],且arr[q+1..j]中的每一个值都大于arr[q]
//若k<=q-i,则数组arr[l..r]前k大的值,就等于子数组arr[i..q-1]前k大的值
//否则,数组arr[l..r]前k大的值,就等于左侧子数组全部元素,加上右侧子数组arr[q+1..j]中前k-(q-i)大的值
vector<int>topKFrequent(vector<int>&nums,int k)
{
unordered_map<int,int>maps;
for(auto i:nums)
{
maps[i]++;
}
vector<pair<int,int>>values;
for(auto &j:maps)
{
values.push_back(j);
}
vector<int>res;
qSort(values,0,values.size()-1,res,k);
return res;
}
void qSort(vector<pair<int,int>>&values,int start,int end,vector<int>&res,int k)
{
//随机选取中枢
int picked=rand()%(end-start+1)+start;
swap(values[picked],values[start]);
int pivot=values[start].second;
int index=start;
for(int i=start+1;i<=end;i++)
{
if(values[i].second>=pivot)
{
swap(values[index+1],values[i]);
index++;
}
}
swap(values[start],values[index]);
if(k<=index-start)
{
qSort(values,start,index-1,res,k);
}
else{
for(int i=start;i<=index;i++)
{
res.push_back(values[i].first);
}
if(k>index-start+1)
{
qSort(values,index+1,end,res,k-(index-start+1));
}
}
}
};