单调队列与应用
Posted 白龙码~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调队列与应用相关的知识,希望对你有一定的参考价值。
文章目录
单调队列
单调队列,就是满足从队头到队尾单调递增或递减的队列。与FIFO队列不同的是,单调队列使用deque
作为底层数据结构。
一、push
单调队列从队尾入队,以单调递减队列为例(即队头为最大值):
-
如果相邻元素小于新元素,则将其出队。
注:正因这里会有队尾出队的情况,因此选择
deque
比较合适。 -
如果相邻元素大于等于新元素,则将新元素入队。
void Push(int x)
while (!dq.empty() && x > dq.back())
dq.pop_back();
dq.push_back(x);
二、get
单调队列的队头就是当前队列中的最值。
int Get()
if (dq.empty())
return -1;
return dq.front();
三、pop
pop用来将单调队列的最值弹出,即删除队头元素。
void Pop()
if (!dq.empty())
dq.pop_front();
四、单调队列的应用:滑动窗口最值问题
给定一个数组 nums 和滑动窗口的大小k,请找出所有滑动窗口里的最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
问题分析:
-
朴素暴力解法:窗口每右移一次,则通过遍历窗口内元素的方式找到最大值。
-
单调队列解法:将窗口内的元素全部加入单调减队列,即队头为最大值。
窗口右移时,判断左边出去的元素是否是队头元素,如果是,则将队头pop,最后将右边新增的元素入队列即可。
单调队列代码实现:
class MonotoneQueue
deque<int> dq;
public:
void Push(int x)
while (!dq.empty() && x > dq.back())
dq.pop_back();
dq.push_back(x);
int Get()
if (dq.empty())
return -1;
return dq.front();
void Pop()
if (!dq.empty())
dq.pop_front();
;
vector<int> maxSlidingWindow(vector<int>& nums, int k)
MonotoneQueue mq;
int n = nums.size();
int left = 0, right = 0;
// 初始化单调队列
while (right < k)
mq.Push(nums[right]);
++right;
vector<int> res;
res.push_back(mq.Get());
while (right < n)
int x = nums[left++];
if (x == mq.Get())
mq.Pop();
mq.Push(nums[right++]);
res.push_back(mq.Get());
return res;
以上是关于单调队列与应用的主要内容,如果未能解决你的问题,请参考以下文章