什么叫单调栈呢?就是单调递增或是单调递减的栈。
适用于什么样的题呢?
柱状图中最大的矩形
柱状图中最大的矩形:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1
,给定的高度为 [2,1,5,6,2,3]
。
输入: [2,1,5,6,2,3]
输出: 10
一般式:
- 输入的是数组且求的是这个数组中的某一范围内的最大值。
class Solution(object):
def largestRectangleArea(self, heights):
"""
:type heights: List[int]
:rtype: int
"""
#这个地方容易出错,为什么要加个0呢?因为我们希望所有的栈内元素都出栈
heights.append(0)
h = heights
#递增栈
stack = []
#初始值
res = 0
for i, values in enumerate(h):
while stack and values < h[stack[-1]]:
remove_val = stack[-1]
#stack要弹出最高值
stack.pop(-1)
if stack == []:
begin = 0
else:
#注意,这里必须是`stack[-1]+1`.
begin = stack[-1]+1
print('**'+str(begin))
print(remove_val)
res = max(res, h[remove_val]*(i-begin))
stack.append(i)
print(stack)
return res
步骤:
- 先给数组append一个0
- 然后创建一个栈和一个初始值
- 然后直接判断,这个栈是不是递增的栈,如果不是,就把不符合递增的下标仍了,仍的过程中计算它的最大值并记录比较。
问题:为什么begin = stack[-1]+1
print('**'+str(begin)+'^^^'+str(remove_val))
仔细观察即可发现。
在加一道菜:
是不是符合上述规律呢?
def get_max(arr):
if arr == []:
return 0
arr.append(0)
g = arr
stack = []
res = 0
for i,values in enumerate(g):
while stack and values<g[stack[-1]]:
remove_val = stack[-1]
stack.pop()
if stack==[]:
begin = 0
else:
begin = stack[-1]+1
print('**'+ str(begin))
print(stack[-1])
#仅仅是这里需要依据不同的变换
res = max(res, g[remove_val]*sum(g[remove_val:i]))
stack.append(i)
return res
a = [1,2,5,3,4]
b = get_max(a)
# print(b)
接下来,我们来看一看,单调递增的栈
接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水
上面是由数组[0,1,0,2,1,0,1,3,2,1,2,1]
表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
class Solution:
def trap(self, height):
len_h = len(height)
if len_h < 3:
return 0
h = height
stack, res = list(), 0
for i,values in enumerate(h):
while stack and values>h[stack[-1]]:
tmp = stack.pop()
if stack:
‘’‘
主要提示:下面的这行代码是依据不同的题有不同的。
但是相同之处都是`res=res+min()*距离`
需要变的就是`min()`
`min()`里一般是当前值即`values`,一个是`stack` `pop`之后的最后一个值即stack[-1].
另外可以发现在递增栈里是h[stack[-1]+1:i],而在递减栈里是(i - stack[-1] - 1),即做差。
’‘’
res = res + (min(values,height[stack[-1]]) - h[tmp])*(i - stack[-1] - 1)
stack.append(i)
return res
记住这写规律即可。