单调栈是一种特殊的栈,栈内元素保持递增或者递减。
单调栈有两个性质:
1.满足从栈顶到栈底的元素具有严格的单调性
2.满足栈的后进先出特性越靠近栈底的元素越早进栈
利用单调栈,可以找到从左/右遍历第一个比它小/大的元素的位置,在某些问题中可以将时间复杂度从O(N^2)降低为O(N).如leetcode 84. Largest Rectangle in Histogram.
这道题的描述是:在二维平面中,给定一系列宽度为1的矩形的高度,求出这些矩形围成的最大的面积。如下图所示:
分析:
这道题中受单调栈的启发,我们可以维护一个从栈底到栈顶递增的栈stack,每次从高度列表中取出一个元素的时候将其与栈顶元素比较,若大于栈顶元素,则入栈,否则找到第一个比它小的元素,使其在这个元素后面入栈。在每次操作时,python中有一个trick比较常用,即使用枚举函数enumerate同时获取索引和值入栈(top k也可以这样做)。同时,我们维护一个记录最大面积的变量,使其每次在获得更大面积的时候更新。这样做的好处是,可以避免申请额外的空间存储所有的面积再求最大值。代码如下:
class Solution(object):
def largestRectangleArea(self, heights):
heights.append(-1)
stack = [(0,-1)]
maxArea = -1
for i,h in enumerate(heights):
index0 = i
while stack and stack[-1][0] > h:
h0, index0 = stack.pop()
area0 = h0*(i-index0)
if area0 > maxArea:
maxArea = area0
stack.append((h, index0))
return maxArea
值得注意的是,由于最后一个元素入栈后,这个时候其实还没有结束对比,因此需要在最后面设置一个标志位(这里为-1),保证最后一个元素也能被计算。
类似的题目