classSolution:deftrap(self, height: List[int])->int:# 使用方法:动态规划"""
分析思路:
对于下标i,水能到达的最大高度为i左右两边的最大高度(包括i本位)的最小值
解释:左边最大高度为2,i为1,右最大高度为3,2 < 3,所以水能到达的最大高度为2
i位置上能存储的水量,为水能到达的最大高度-i本位的高度height[i]
创建两个数组:
leftMax:表示下标i及其左边的位置中,height的最大值
rightMax:表示i及其右边的位置中,height 的最大值
leftMax[i] = max(leftMax[i-1], height[i]) 1<=i<=n-1
rightMax[i] = max(rightMax[i+1], height[i]) 0<=i<n-1
最终的结果:
i位置能接的水量,等于min(leftMax[i], rightMax[i])-height[i]
"""
n =len(height)
res =0# 处理特殊情况if n ==0:return res
leftMax =list()
rightMax =[0]*n # 提前使用0进行占位,来避免列表本身的索引缺陷
leftMax.append(height[0])
rightMax[n-1]= height[n-1]# 直接进行赋值覆盖# print(rightMax)for i inrange(1, n):
leftMax.append(max(leftMax[i-1], height[i]))# print(leftMax)for i inrange(n-2,-1,-1):
rightMax[i]=max(rightMax[i+1], height[i])# 注意这里是直接赋值,不是插入# print(rightMax)for i inrange(n):
res +=(min(leftMax[i], rightMax[i])- height[i])return res
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
使用双指针方法
classSolution:deftrap(self, height: List[int])->int:# 使用双指针简化空间复杂度
n =len(height)
res =0if n ==0:return res
# 定义两个指针
left =0
right = n-1
leftMax =0
rightMax =0while left < right:
leftMax =max(leftMax, height[left])
rightMax =max(rightMax, height[right])# 使用两个指针,不断更新结果,边遍历,边计算if height[left]< height[right]:# 一定有leftMax < RightMax
res +=(leftMax - height[left])
left +=1"""
原因:
单纯看存左到右计算:(建议画个图)
当 left < leftMax, 从左到右计算的话,这个时候leftMax必须小于right, left本位的水量才能一次性确定下
来,就有left < leftMax < right <= rightMax,left += 1,否则的话,就会自动交给从右到左计算的那部
分程序处理
当 left == leftMax,从左到右计算的话,说明left本位是存不了水,这个时候left大于或者小于right都无所
谓(仅仅针对从左到右),但是left要移动,干脆让它小于right的情况下移动和上面保持一致就行了
"""else:
res +=(rightMax - height[right])
right -=1return res