给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)
数据范围:数组长度
,数组中每个值满足
,保证返回结果满足
要求:时间复杂度
[3,1,2,5,2,4]
5
数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水 ,如题面图。
[4,5,1,3,2]
2
# 递归(原始方法的形参,不够递归使用,再创一个) class Solution: ## 写法一(用类属性记录结果,比方法同级,不会释放) res = 0 def find(self, arr, ind1, ind2): # 终止条件 if ind1 == ind2: return # 本次计算 if arr[ind1] <= arr[ind2]: init_val = arr[ind1] while True: ind1 += 1 if arr[ind1] < init_val: self.res += init_val - arr[ind1] else: break else: init_val = arr[ind2] while True: ind2 -= 1 if arr[ind2] < init_val: self.res += init_val - arr[ind2] else: break # 继续计算相同的子问题 self.find(arr, ind1, ind2) def maxWater(self , arr: List[int]) -> int: self.find(arr, 0, len(arr) - 1) return self.res ## 写法二(传入一个变量记录结果,依次累计,最终结果一层层return) def find(self, arr, ind1, ind2, res=0) -> int: """ ind1: int, 左边的游标 ind2: int, 右边的游标 res: int, 用于记录之前已接的雨水数量 思路: res记录之前的雨水, 然后加上本轮的雨水, 最终一层层最终返回结果 """ # 终止条件 if ind1 == ind2: return res # 最后一轮雨水量为零, 返回最终结果 # 本次计算 if arr[ind1] <= arr[ind2]: init_val = arr[ind1] while True: ind1 += 1 if arr[ind1] < init_val: res += init_val - arr[ind1] # 加上本坑的雨水数量 else: break else: init_val = arr[ind2] while True: ind2 -= 1 if arr[ind2] < init_val: res += init_val - arr[ind2] else: break # 继续计算相同的子问题 return self.find(arr, ind1, ind2, res) def maxWater(self , arr: List[int]) -> int: return self.find(arr, 0, len(arr) - 1) ## 写法三(每次只关心当前轮结果,一层层累加,最后一轮return标志层结束,并return所有层的最终结果) def find(self, arr, ind1, ind2) -> int: """ ind1: int, 左边的游标 ind2: int, 右边的游标 """ # 终止条件 if ind1 == ind2: return 0 # 结束池塘雨水量为零 # 本次计算 res = 0 # 记录本池塘的雨水量 if arr[ind1] <= arr[ind2]: init_val = arr[ind1] while True: ind1 += 1 if arr[ind1] < init_val: res += init_val - arr[ind1] # 加上本坑的雨水数量 else: break else: init_val = arr[ind2] while True: ind2 -= 1 if arr[ind2] < init_val: res += init_val - arr[ind2] else: break # 继续计算相同的子问题 res += self.find(arr, ind1, ind2) # 加上之后池塘的雨水量 return res # 返回所有池塘的累加结果 def maxWater(self , arr: List[int]) -> int: return self.find(arr, 0, len(arr) - 1)
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # max water # @param arr int整型一维数组 the array # @return long长整型 # class Solution: def maxWater(self , arr: List[int]) -> int: ret = 0 stack = [] for i in range(len(arr)): if stack: if arr[stack[-1]] >= arr[i]: stack.append(i) else: tmp = 0 bottom = 0 while stack: tmp = stack.pop() if i - tmp == 1: bottom = arr[tmp] if i - tmp > 1: ret += (i-tmp-1) * (min(arr[i], arr[tmp]) - bottom) bottom = arr[tmp] if bottom >= arr[i]: stack.append(tmp) break stack.append(i) else: stack.append(i) return ret
可惜牛客的Python没有numpy这个模块
import numpy as np
class Solution:
def maxWater(self , arr ):
TotalRightRain=0
TotalLeftRain=0
arr=np.array(arr)
if arr.argmax()!=len(arr)-1:
right=arr[(arr.argmax()+1):]
while True:
RightRainList = right[:right.argmax()]
if right.argmax() == len(right) - 1:
if len(RightRainList) == 0:
break
for i in RightRainList:
TotalRightRain += right[right.argmax()] - i
break
elif len(RightRainList) == 0:
right = right[right.argmax() + 1:]
continue
else:
for j in RightRainList:
TotalRightRain += right[right.argmax()] - j
right = right[right.argmax() + 1:]
if arr.argmax()==0:
return TotalRightRain+TotalLeftRain
else:
left=arr[:arr.argmax()]
while True:
LeftRainList=left[:left.argmax()]
if left.argmax() == len(left)-1:
left=left[:left.argmax()]
if len(left)==0:
break
continue
elif len(LeftRainList)== 0:
for m in left[left.argmax():]:
TotalLeftRain+=left[left.argmax()]-m
break
else:
for n in left[left.argmax():]:
TotalLeftRain += left[left.argmax()] - n
left=LeftRainList
return TotalRightRain+TotalLeftRain