这里是我的blog:有更多算法分享。排版可能也会更好看一点=v=
https://endlesslethe.com/monotone-queue-and-stack-tutorial.html
前言
单调栈和单调队列算是栈和队列的高级应用吧,在公司面试中应该是不怎么会出现的(除非算法岗?)。
因为原理比较简单,网络上的相关资料反而对于这两个东西说得都不甚清楚,尤其是它们的应用方法。最基本的两本中文算法书“紫书”和“白皮”都没有提到。
而我因为平日要做的事情也很多,仓促中写下的这篇文章难免表达上会有不清晰的地方和各种疏漏,希望读者不吝赐教=v=。
栈和队列这两种基础数据结构戳:TBC。
先说明一下,无论是栈还是队列,我们把元素进入的一端称作“尾部”,并用双引号标出,另一端称作“尾部”。对于栈,头部即是栈底,尾部即是栈顶。对于队列,头部对应队首,尾部对应队尾。
注:我不确定单调队列是否翻译成monotone queue,算法导论上没有提到这个数据结构,Bing上也没有搜索到对应它的结果(倒是返回了关于优先队列的结果)。
单调栈
我们都已经非常熟悉栈了,它具有先入后出的性质。而单调栈为了满足单调的要求,增加了一个性质:
- 从栈顶到栈底的元素是严格递增(or递减)
显然,这和我们的正常的流程有一定矛盾之处——如果栈中是5 4 3 2 1,如果压入3怎么办?
原来我们只需要添加到栈尾即可,现在则需要将3 2 1弹出,再压入3,栈变成5 4 3
注:弹出的元素我们直接舍弃掉。
具体进栈过程
- 对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。
- 对于单调递减栈,则每次弹出的是大于e或者等于e的元素。
一个单调递增栈的例子:
进栈元素分别为3,4,2,6,4,5,2,3
第i步 | 操作 | 结果 |
---|---|---|
1 | 3进栈 | 3 |
2 | 3出栈,4进栈 | 4 |
3 | 2进栈 | 4 2 |
4 | 2、4出栈,6进栈 | 6 |
5 |