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()出去!