主要学习队列的一些经典用法。
滑动窗口最大值
题目有难度,单调队列的思路很重要,要多看视频复习
class Solution {
private:
class MyQueue{
public:
deque<int> que;
void popVal(int val){
if(!que.empty() && val == que.front())
{
que.pop_front();
}
}
void pushVal(int val){
while(!que.empty() && val > que.back()){
que.pop_back();
}
que.push_back(val);
}
int getMax(){
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> res;
for(int i = 0; i < k; i++)
{
que.pushVal(nums[i]);
}
res.push_back(que.getMax());
for(int i = k; i < nums.size(); i++)
{
que.popVal(nums[i-k]);
que.pushVal(nums[i]);
res.push_back(que.getMax());
}
return res;
}
};
前 K 个高频元素
这部分有一些新的知识点,比如优先级队列、自定义比较器。
优先级队列:
优先级队列是一种特殊的队列,它比常规队列多了一个特性,即每个元素都有一定的优先级,数据项的出队顺序是按照每个元素的优先级权重进行的,而不是严格的先进先出(FIFO)规则。
优先级队列的常见应用包括:CPU任务调度,图形的广度优先搜索中用于维护顶点的访问次序等。
在C++ STL库中,优先级队列被定义为一种容器适配器,可以使用任何底层容器模型,比如一个向量或者一个 deque,来创建一个优先级队列。下面是一个最简单的优先级队列的定义示例:
#include <queue>
std::priority_queue<int> pq;
这段代码定义了一个存放int类型的优先级队列,比较函数是less,所以这是一个最大元素堆。队列中元素最大的元素在堆的顶部,每次出队都会弹出当前堆中最大的元素。
也可以自定义优先级队列中的比较规则,例如:
struct Compare {
bool operator()(const int& a, const int& b) {
return a > b;
}
};
std::priority_queue<int, std::vector<int>, Compare> pq;
这里我们定义了一个比较函数对象,使得优先级队列成为最小元素堆。在这个优先级队列中,大小关系是由我们自定义的 Compare 操作符决定的,小的元素优先级更高。所以这个优先级队列每次会优先弹出最小的元素。
自定义比较器:
在定义比较函数对象时,这个函数意味着当operator()
返回true
时,第一个参数应该被视为优先级较低的元素。
所以如果我们有bool operator()(const int& a, const int& b) { return a > b; }
,这个函数在 a > b
(即a
比b
大)时返回true
。这意味着当a
比b
大的时候,a
应该被视为优先级较低。这就建立了一个最小元素堆。
所以,如果你想要的是最大元素堆,那你的比较函数对象应该像这样:
struct Compare {
bool operator()(const int& a, const int& b) {
return a < b;
}
};
这样当a
小于b
的时候,a
会被视为优先级较低的元素,因此大的元素b
(优先级高的)会先被弹出,这就成了一个最大元素堆。
题目实现代码:
class Solution {
public:
class mycomparison{
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs){
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> myMap;
for(int i = 0; i < nums.size(); i++)
{
myMap[nums[i]]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> my_pri;
for(unordered_map<int, int>::iterator it = myMap.begin(); it != myMap.end(); it++)
{
my_pri.push(*it);
if(my_pri.size() > k)
{
my_pri.pop();
}
}
vector<int> result(k);
for(int i = k-1; i >=0; i--)
{
result[i] = my_pri.top().first;
my_pri.pop();
}
return result;
}
};