Monostack:找邻居助手
Next Greater Element
假设一队人前后站在一起,每个人向前看,由于前面的高个儿挡住了视线,所以只能看到自己和那个歌高个儿之间的同学。问题来了:如何能快速知道每个人前面挡住视线的第一个高个儿呢?于是有了这样的对话:
Bob说:“你看,我们从左往右一个个来看,对于每一个人来说,我们向前看第一个比TA高的就好了。“
Alice说:“那对于每一个人来说,都要比较与前面所有人的身高啊。怎么感觉有更快的方法?如果找到一个高个儿,TA不就是所有之前比TA矮的人的答案了吗?
这种把“之前比TA矮的人“存下来的数据结构就是单调栈。
模版如下[LC 739]:
stack = []
for n in nums:
while stack and n>stack[-1]:
m = stack.pop() # m的nextGreater是n
stack.append(n)单调栈
单调栈利用了“先入后出“的原则方便我们来寻找nextGreaterElement或是nextSmallerElement。有些题要在数组中找对子,单个枚举可能要O(n²),如果要寻找O(n)时间的方法有可能是用单调栈来用空间换时间。

有时候需要把index存下来,来找到nextGreaterElement的等待时间。
例题:132 模式
我们把数字反转,就变成了寻找231模式。那么从左到右,我们可以用单调递减栈保存2和3。题目只要求寻找是否存在231模式,那么我们利用单调递减栈的性质:所有弹出的数字都比栈中的数字小,把“3“存在栈中,弹出的数字是“2“。我们反向遍历数组,然后看到有比存在的弹出数字更小的“1“,就找到了答案。
下面mmax=stack.pop()本也可以写作mmax=max(mmax, stack.pop())。不过由于单调栈的性质:最后弹出的数字相对最大,所以可以略去这个比较。
参考代码:
Last updated
Was this helpful?