LeetCode链接
计算每一列可以接的雨水 对每一列 寻找其左右的最大高度 时间复杂度 O(N^2)
class Solution :
def trap ( self, height: List[ int ] ) - > int :
sum = 0
heightLen = len ( height)
for i in range ( 1 , heightLen - 1 ) :
curHeight = height[ i]
maxLeft, maxRight = curHeight, curHeight
for j in range ( 0 , i) :
maxLeft = max ( maxLeft, height[ j] )
for j in range ( i + 1 , heightLen) :
maxRight = max ( maxRight, height[ j] )
sum += min ( maxLeft, maxRight) - curHeight
return sum
动态规划 预先处理好 元素i 及其左右两边的最大值 时间复杂度O(N) 空间复杂度O(N)
class Solution :
def trap ( self, height: List[ int ] ) - > int :
heightLen = len ( height)
leftMax = [ height[ 0 ] ] + [ 0 ] * ( heightLen - 1 )
rightMax = [ 0 ] * ( heightLen - 1 ) + [ height[ - 1 ] ]
for i in range ( 1 , heightLen) :
leftMax[ i] = max ( leftMax[ i - 1 ] , height[ i] )
for i in range ( heightLen - 2 , - 1 , - 1 ) :
rightMax[ i] = max ( rightMax[ i + 1 ] , height[ i] )
return sum ( min ( leftMax[ i] , rightMax[ i] ) - height[ i] for i in range ( 1 , heightLen - 1 ) )
双指针 降低动态规划版本的空间复杂度 时间复杂度O(N) 空间复杂度O(1)
class Solution :
def trap ( self, height: List[ int ] ) - > int :
'''
双指针基于以下几个重要条件:
1、i列能接的水 为 min(leftMax, rightMax) - height[i]
2、双指针分别从头尾开始 left, right = 0, len - 1 left右移 right左移
初始时 leftMax, rightMax = height[left], height[right]
此时若 height[left] < height[right] 则leftMax < rightMax
较低的left处会有积水 量为 leftMax - height[left]
累加后,left+=1 并尝试更新leftMax right没变 有 height[right] = rightMax
此时
若height[left] < height[right] 则leftMax 仍< rightMax
若height[left] >= height[right] 则leftMax 必>= rightMax
由此可得 双指针解法的核心:
1、每次只计算 较低处的积水 计算完之后 左移或右移 一次只移动一边
2、height[left] < height[right] 必有 leftMax < rightMax
'''
heightLen = len ( height)
left, right = 0 , heightLen - 1
leftMax, rightMax = 0 , 0
sum = 0
while left < right:
leftMax = max ( leftMax, height[ left] )
rightMax = max ( rightMax, height[ right] )
if height[ left] < height[ right] :
sum += leftMax - height[ left]
left += 1
else :
sum += rightMax - height[ right]
right -= 1
return sum
单调栈 时间复杂度O(N)
class Solution :
def trap ( self, height: List[ int ] ) - > int :
indexStack = [ ]
sum = 0
for i in range ( len ( height) ) :
while indexStack and height[ i] > height[ indexStack[ - 1 ] ] :
bottom = indexStack. pop( )
if not indexStack:
break
left = indexStack[ - 1 ]
sum += ( i - left - 1 ) * ( min ( height[ i] , height[ left] ) - height[ bottom] )
indexStack. append( i)
return sum