相关单调栈问题:
https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/bao-li-jie-fa-zhan-by-liweiwei1419/
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
class Solution:
def largestRectangleArea(self, heights):
stack = []
# 加入哨兵值,便于原先heights中的最后位置的值弹出
# 因为需要比最后一个值小的值,才能把最后一个值卡在
# 中间计算面积
heights = [0] + heights + [0]
res = 0
for i in range(len(heights)):
#print(stack)
# stack[-1] 表示栈顶
# 当前值比栈顶的值小的时候,相当于两个比栈顶小的值把
# 栈顶位置的数卡在中间,比如5,6,2,栈顶数为6
# 此时可以计算栈顶6围成的矩形面积
while stack and heights[stack[-1]] > heights[i]:
tmp = stack.pop()
# 栈里面后面比前面大的时候才压入,相当于顺序压入
res = max(res, (i - stack[-1] - 1) * heights[tmp])
stack.append(i)
return res
if __name__ == '__main__':
heights = [2, 1, 5, 6, 2, 3]
solution = Solution()
res = solution.largestRectangleArea(heights)
print(res)
梳理
- 如果一直是增序,则stack栈顶,比i小一,每个for i+1 , 到for结尾i+1入栈。
- 当遇到降序时,即先将栈顶(第一次降序,栈顶为i-1)出栈。
- 用出栈值 * (i - 当前栈顶值 - 1), 第一次降序,在上一步出栈后, 当前栈顶值应比 i 小2,再减去出栈的1.
如果不是第一次降序,则当前栈顶值比i 小 n
heights = [2, 1, 5, 6, 2, 3]
加入哨兵
heights = [0,2, 1, 5, 6, 2, 3,0]
初始栈为空 stack = []
第一轮
i = 0
先把开头的哨兵 0 压入栈
stack = [0]
第二轮,
i = 1
heights[stack[-1]] = heights[stack[0]] = heights[0] = 0
heights[i] = heights[1] = 2
不满足while, 直接将i = 1 压入栈
stack = [0, 1]
第三轮
i = 2
heights[stack[-1]] = heights[1] = 2
heights[i] = heights[2] = 1
heights[stack[-1]] > heights[i]