单调队列概念和技巧

单调队列概念和技巧

总结

单调队列适合在数组/集合中,求滑动窗口的最值问题。

1.概念

单调队列相比单调栈,不同点就是利用第一种实现方式的单调栈,并接受删除栈底的数;表现为可以在队列尾部插入和删除数据(同第一种单调栈栈顶操作),并且可以在队列头部删除数据。

2.实现

单调栈主要用来找出一个滑动窗口中的最值。所以对于原数组中的每一个值,都会在队列尾部进行进队操作,进队操作和单调栈的进栈操作一样。当队列头部的元素已经不属于该窗口时就将该元素从头部删除。

例子:

找出每一个窗口中的最小值——构建一个单调递增队列
原数组:[2,1,7,3,5,4,6,8] 
假设我们分析需要的窗口大小为3
队列中存储的是数组索引。
(1)队列空,2入队列 queue = [0] 
(2)1<2 queue = [1] 将元素2对应的下标0从队尾删除 
(3)7>1 queue = [1,2] 将元素7对应的下标7入队 
到第(3)步,队尾的刚好遍历完成第一个窗口[2,1,7],此时最小值就是队列中的队首元素1。
(4)1<3<7 queue = [1,3] 此时窗口[1,7,3]的最小值也是队首元素1. 
(5)5>3 queue = [1,3,4] 此时队首元素1已经不是下一个窗口中的元素,将其删除 
	queue = [3,4] 此时队首元素3就是该窗口[7,3,5]的最小值。
(6)3<4<5 queue = [3,5] 此时队首元素3就是窗口[3,5,4]的最小值。
(7)6>4 queue = [3,5,6] 此时队首元素3已经不是该窗口元素,将其删除
	queue = [5,6] 此时队首元素4就是窗口[5,4,6]的最小值。
(8)8>6 queue = [5,6,7] 此时队首元素4就是窗口[4,6,8]的最小值。

通过例子可以发现,队首元素就是符合我们需要的窗口的最值。

3.特征

以单调递增队列进行举例,单调递减队列类似。

假设队列存储的是原数组元素对应的下标,当遍历到下标26时,队列为:
3,5,[8,20,25] 
方括号[]表示队列中的元素,此时队列中的元素为(8,20,25),已经不在队列中的元素为(3,5)它们是之前从队首删除的元素。
通过之前的单调栈的特点我们知道,下标5,8之间的元素都大于下标为5和8的元素,所以此时的下标为8的元素是窗口[6-25]的最小值。同理窗口[9-25]的最小值为下标为20的元素;窗口[21-25]的最小值是下标为25的元素。
所以假如这一时刻(遍历到元素26时),我们需要分析从下标9开始的窗口,则目前的队首元素8就需要出队列了,因为它已经不属于我们要分析的窗口,此时队列为[20,25]

4.使用技巧

通过上面的分析,适合场景已经很明确。

单调队列适合在数组/集合中,求滑动窗口的最值问题。

例子:leetcode 239

在这里插入图片描述

这个题很明显符合单调队列的特点。

例子:leetcode 1438

在这里插入图片描述

本题可以想到使用一个窗口表示一个满足要求的数组-窗口中最大值-最小值<=limit。
窗口左边首先不动,右边向下一个元素移动,如果下一个元素假如窗口,此时窗口的最大值-最小值<=limit,则该窗口表示的数组符合要求;如果加入这个元素,窗口最大值-最小值>limit,则该窗口表示的数组不符合要求,此时移动窗口左边,直到窗口满足要求。
所以该问题需要计算每个滑动窗口的最大值和最小值的差,这里就可以用到单调队列,分别构造一个单调递增队列(求最小值),单调递减队列(求最大值)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值