单调栈 和 单调队列

1. 使用场景

一个数组,对于第i个元素,找出离它最近且比它大/小的两边的index分别是多少?

比如“LeetCode接雨水”这道题,就需要找出距离某个index最近且比它大的两边的index,

然后才可以以该index为hight,以right - left + 1位width,求出可以接到的雨水。

再比如“柱状图中矩形最大”这道题:

 先不看矩形最大,按照动态规划的原则,需要先找出以该index为height的最大矩形的面积;

和“接雨水”相反,需要找出距离该index最近且小于该index高度的左右两边index作为left和right,求出width。

以上就是“一个数组,对于第i个元素,找出离它最近且比它大/小的两边的index分别是多少?”,大于小于各举一例。

2. 什么是单调栈?

一个数组a[5] = {3, 1, 4, 2, 5},存放到一个单调递增/递减的栈中,存放的时候记录一下比该index小/大的元素index,放到一个数组中;

假如新来的元素index打破了栈的递增/递减规则,就从栈中移除打破规则的元素。

比如a[5] = {3, 1, 4, 2, 5},找出距离index最近且小于该index的左右元素,需要一个单调递增栈,步骤:

初始:栈为空,left = -1

3放进去,left[0] = -1,最终栈元素:3

1准备放进去,发现3 > 1,把3拿出来,left = -1;最终栈元素:3

4准备放进去,发现里面存放的是1,left = 1,最终栈元素:1,4

……

假如准备放进去1,左边的值3比其大,那么左边的值3的放入,不会影响1寻找左边的值,因为3的放入只会拿出比3大的值!

假如左边的值比该值小,比如1,4的放入,那么直接找到左边的值了。

3. 单调队列

类似单调栈,也存在单调队列!

单调队列,首先是求比某个元素大/小的一些元素,队列还可以从队首弹出,在“滑动窗口的最大值239”这道题有应用:

对于一个数组,求滑动窗口大小为K,滑动过程中的窗口最大值;

基于一个规则:假如大小为K的队列中,i < j且 nums[i] < nums[j], 即后面的数比前面的大,那么前面的数就没有保存的必要;

单调队列中保存的值,都是单调递减的,一旦该值比队列中某些数大,队列中的小的值就可以pop_back()出去!

原文地址:https://www.cnblogs.com/Younger-Zhang/p/15063545.html