接雨水
题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
解题方法
class Solution:
def trap(self, height: List[int]) -> int:
"""
暴力法
结果: 超出时长
res , left_max, right_max = 0, -1, -1
for i, h in enumerate(height):
left_max = max(height[:i]) if len(height[:i])>0 else -1
right_max = max(height[i:]) if len(height[i+1:])>0 else height[-1]
if min(left_max, right_max)>h: res += min(left_max, right_max)-h
return res
"""
"""
存储左边最大值,减小每次计算max(left_height)的时间
res , left_max, right_max = 0, -1, -1
for i, h in enumerate(height):
if h>left_max: left_max = h
right_max = max(height[i:]) if len(height[i+1:])>0 else height[-1]
res += min(left_max, right_max)-h
return res
"""
"""
存储每个元素对应的左边及右边最大值, 减小计算最大值是的计算量
res , left_maxs, right_maxs = 0, [-1], [-1]
for h in height[:-1]:
if h>left_maxs[-1]: left_maxs.append(h)
else: left_maxs.append(left_maxs[-1])
for i in range(len(height)-1, 0, -1):
if height[i]>right_maxs[-1]: right_maxs.append(height[i])
else: right_maxs.append(right_maxs[-1])
right_maxs.reverse()
#print(left_maxs, right_maxs)
for i, h in enumerate(height):
if min(left_maxs[i], right_maxs[i])>h: res += min(left_maxs[i], right_maxs[i])-h
return res
"""
"""
利用双指针,对左右left_max,right_max进行存储
if not height: return 0
left_max, right_max = height[0], height[-1]
left, right, res = 0, len(height)-1, 0
while(left<=right):
if left_max<=right_max:
if height[left]>=left_max: left_max= height[left]
else: res= res+left_max-height[left]
#print(left, res)
left+=1
else:
if height[right]>=right_max: right_max = height[right]
else: res += right_max - height[right]
#print(right, res)
right-=1
return res
"""
if not height: return 0
n = len(height)
stack = []
res = 0
for i in range(n):
while stack and height[stack[-1]] < height[i]:
tmp = stack.pop()
if not stack: break
res += (min(height[i], height[stack[-1]]) - height[tmp]) * (i-stack[-1] - 1)
stack.append(i)
return res