求前K个最大数,最小数,第K个最大数,或者 出现频率为第K大的单词是哪个 此类问题,首先想到的就是排序,但是求第K最大而已,并不要求完全有序,所以 想到了 大顶堆 和小顶堆
我们可以用到 优先级队列 priority_queue,它实际上是一个队列,但是它的功能是始终保持队首元素是当前元素的最大值
定义:priority_queue
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 是仿函数,决定了优先队列的 比较方式
默认为大顶堆:priority_queue
当然也可以自定义类型然后自定义相匹配的仿函数
1.首选由简单的例题着手:
本题要求数组中第K大的数是多少?
第一想法是进行排序,然后选择合适位置处的元素即可
但是要求是求第K大元素,并不要求对数组进行排序
所以我们只要知道前K个最大元素即可,而对于他们的顺序无关紧要,所以就可以用到优先级队列priority_queue
将数组元素逐渐压入priority_queue,当优先级队列内的元素 大于 (所有元素个数 - k)时,即优先级队列顶端中一定是前K个元素中的某一个了
取出顶端元素压入 数组中,然后找到数组中的最小元素,即为全部元素中的第K大元素
class Solution {
public:
int findKthLargest(vector& nums, int k)
{
vector restmp;
priority_queue pq;//优先级队列
for(auto i : nums)
{
pq.push(i);
if(pq.size() > nums.size()-k)
{
restmp.push_back(pq.top());
pq.pop();
}
}
int kmin =INT_MAX;
for(int i : restmp)
{
if(i <= kmin)
{
kmin = i;
}
}
return kmin;
}
};
2.求数组中,出现频率位于前K次的元素
这题目也不难,容易想到的就是用 哈希map来统计每一个元素出现的次数
然后用优先级队列,但由于 比第一题多了 要考虑的频率,所以我们采用 对组 pair
来记录各个元素出现的频率以及对应的元素。
然后求前K个,用默认的大顶堆即可
class Solution {
public:
vector topKFrequent(vector& nums, int k)
{
unordered_map map;
vector res;
for(int i = 0; i < nums.size(); i++)//统计每个元素的出现的频率
{
map[nums[i]]++;
}
priority_queue> pq; //用大顶堆来记录 频率和对应元素,
//用pair的第一个元素代表频率,第二个元素代表对应该频率对应的元素
for(auto it = map.begin(); it != map.end(); it++)
{
pq.push(make_pair(it->second,it->first));
if(pq.size() > map.size()-k)
{
res.push_back(pq.top().second);
pq.pop();
}
}
return res;
}
};
3.求数组中出现频率为与前K的单词
本来,这道题目和第二题是一样的,只不过把 数据元素 换位 单词元素即可
虽然要求 单词的频率求出现最多的前K个,但是当两个单词出现频率相同时,并不是要求随意摆放,结果中要求
频率相等时,单词按字典顺序摆放,即升序摆放
所以,问题出现了,频率按降序,频率相同时,单词按升序
显然,要定义自己的仿函数
由于也是用对组 pair
所以,仿函数
struct fun
{
bool operator()(pair& p1, pair& p2)
{
if(p1.first < p2.first)//这样记忆吧,小于号代表降序,大于到代表升序
{
return true;
}
else if(p1.first > p2.first)
{
return false;
}
else
{
if(p1.second > p2.second)
{
return true;
}
else
{
return false;
}
}
}
};
所以完整程序如下:
class Solution {
public:
vector topKFrequent(vector& words, int k)
{
vector res;
unordered_map map;
for(auto word : words)
{
map[word]++;
}
priority_queue,vector>,fun> pq;
for(auto it = map.begin(); it != map.end(); it++)
{
pq.push(make_pair(it->second,it->first));
}
while(pq.size() > map.size()-k)
{
res.push_back(pq.top().second);
pq.pop();
}
return res;
}
private:
struct fun
{
bool operator()(pair& p1, pair& p2)
{
if(p1.first < p2.first)//这样记忆吧,小于号代表降序,大于到代表升序
{
return true;
}
else if(p1.first > p2.first)
{
return false;
}
else
{
if(p1.second > p2.second)
{
return true;
}
else
{
return false;
}
}
}
};
};