【题目】
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
【代码】数学法 图像填充切割

class Solution:
def trap(self, height: List[int]) -> int:
ans = 0
h1 = 0
h2 = 0
for i in range(len(height)):
h1 = max(h1,height[i])
h2 = max(h2,height[-i-1])
ans = ans + h1 + h2 -height[i]
return ans - len(height)*h1
【方法2】
按照列进行遍历,每列可以接的雨水数=max(min(该列左侧最高高度,该列右侧最高高度)-当前列的高度,0)
解释:
class Solution:
def trap(self, height: List[int]) -> int:
left=[]
right=[]
for i in range(len(height)):
if left:left.append(max(height[i],left[-1]))
else:left.append(height[i])
height=height[::-1]
for i in range(len(height)):
if right:right.append(max(height[i],right[-1]))
else:right.append(height[i])
right=right[::-1]
idx=0
ans=0
height=height[::-1]
for l,r in zip(left,right):
ans+=max(min(l,r)-height[idx],0)
idx+=1
return ans
【方法3】单调栈
使用单调栈记录从左到右,单调递减的边,因为只有递减的边才有可能存储水。
当遇到一个大于栈顶的边,则表明形成低洼可以存储水(因为栈顶前面的一条边是高于栈顶的,单调栈的特点,而当前的边也高于栈顶,所以形成了一个低洼)。
class Solution:
def trap(self, height: List[int]) -> int:
ans=0
stack=[]
for idx,item in enumerate(height):
while stack!=[] and item>height[stack[-1]]:
top_index=stack[-1]
stack.pop(-1)
if stack==[]:
break
h=min(height[stack[-1]],item)-height[top_index]
w=idx-stack[-1]-1
ans+=h*w
stack.append(idx)
return ans
【方法4】双指针
利用了木桶效应,木桶可以盛水量是由最短木块决定的

class Solution:
def trap(self, height: List[int]) -> int:
left,right=0,len(height)-1
left_max,right_max,ans=0,0,0
while left<right:
if height[left]<height[right]:
if height[left]>left_max:
left_max=height[left]
else:
ans+=left_max-height[left]
left+=1
else:
if height[right]>right_max:
right_max=height[right]
else:
ans+=right_max-height[right]
right-=1
return ans