10.栈与队列Ⅲ
239.滑动窗口最大值
题目描述
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入: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,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
保持如上规则,每次窗口移动的时候,只要访问que.front()就可以返回当前窗口的最大值。
代码实现
class Solution {
public:
//构建一个单调队列类
class MyQueue
{public:
deque<int>que;
//对单调队列,需要重写pop函数,来保证队头始终为最大值
void pop(int value){
if(!que.empty()&&value==que.front())
{
que.pop_front();//队头是最大值,如果要弹的元素等于最大就弹出,说明当前最大值被消掉了。如果不等就不用执行操作。
}
}
//对单调队列,需要重写push函数,因为放元素进来可能破坏单调性,需要保证队列为递减的。
void push(int value)
{
while(!que.empty()&&value>que.