给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)
数据范围:数组长度 ,数组中每个值满足 ,保证返回结果满足
要求:时间复杂度
[3,1,2,5,2,4]
5
数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水 ,如题面图。
[4,5,1,3,2]
2
# class Solution: def maxWater(self , arr: List[int]) -> int: # write code here if not arr: return 0 if len(arr)<3: return 0 low = 0 # 指针 high = len(arr)-1 #指针 maxl = 0 # 左边指针所经的最高高度 maxr = 0 # 右边指针所记录到的最高高度 output = 0 while low < high: maxl = max(maxl, arr[low]) maxr = max(maxr, arr[high]) if maxr > maxl: output += maxl-arr[low] low += 1 else: output += maxr-arr[high] high -= 1 return output
双指针
时间复杂度:O(n) 空间复杂度:O(1)
class Solution: def maxWater(self , arr: List[int]) -> int: if len(arr) == 0: return 0 res = 0 left = 0 right = len(arr) - 1 max_l = 0 max_r = 0 while left < right: max_l = max(max_l, arr[left]) max_r = max(max_r, arr[right]) if max_l > max_r: res += max_r - arr[right] right -= 1 else: res += max_l - arr[left] left += 1 return res
class Solution: def maxWater(self, arr: List[int]) -> int: # write code here n = len(arr) L_height = [0] * n R_height = [0] * n L_height[0] = arr[0] R_height[n-1] = arr[n-1] # 从左往右记录L的高度 for i in range(1, n): L_height[i] = max(arr[i], L_height[i-1]) # 从右往左记录R的高度 for i in range(n-2, -1, -1): R_height[i] = max(arr[i], R_height[i+1]) waters = 0 # 记录答案, 答案 = 左右两边柱子的最小值-当前位置的高度 for i in range(1, n-1): water = min(L_height[i], R_height[i]) - arr[i] waters += max(0, water) return waters
class Solution: def maxWater(self , arr: List[int]) -> int: # write code here n = len(arr) if (n < 3): return 0 num_left = [0 for i in range(n)] num_right = [0 for i in range(n)] num = [0 for i in range(n)] r1 = 0 r2 = 0 #分别从左到右 和 从右到左 for i in range(n): if (arr[i] > r1): r1 = arr[i] num_left[i] = r1 if (arr[n-1-i] > r2): r2 = arr[n-1-i] num_right[n-1-i] = r2 for i in range(n): num[i] = min(num_left[i], num_right[i]) return (sum(num) - sum(arr))
def maxWater(self , arr: List[int]) -> int: # write code here highest = max(arr) highest_ind = arr.index(highest) water = 0 left = arr[0] for i in range(1, highest_ind): if arr[i] < left: water += left - arr[i] else: left = arr[i] right = arr[-1] for i in range(len(arr)-1, highest_ind, -1): if arr[i] < right: water += right - arr[i] else: right = arr[i] return water
# 双指针 class Solution: def maxWater(self , arr: List[int]) -> int: # write code here n=len(arr) L=1 R=n-2 maxL,maxR=arr[0],arr[n-1]# 左侧/右侧的最大值 res=0 while L<=R: if maxL<maxR: t=maxL-arr[L] if t>0: res+=t maxL=max(maxL,arr[L]) L+=1 else: t=maxR-arr[R] if t>0: res+=t maxR=max(maxR,arr[R]) R-=1 return res
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # max water # @param arr int整型一维数组 the array # @return long长整型 # 左成云算法课讲的解法 class Solution: def maxWater(self , arr: List[int]) -> int: # write code here left_most = 0 right_most = len(arr)-1 # 双指针,初始指针第一个位置,和最后一个位置,这两个位置不可能装水,设为初始左右边界 water = 0 while left_most < right_most: # 当两个指针相遇,循环结束 #判断两端的指针所对应的柱子哪个矮一些,矮的为短板,决定最多接多少雨水 #如果左边的较小,用一个cur指针指向左边位置加一,如果cur指针位置小于左 #边的边界,则可计算雨水数目,arr[left_most]-arr[cur],因为此时的局限 #在左边,如果cur位置高于左边界,更新左边界,进入外层大循环 if arr[left_most] <= arr[right_most]: cur = left_most+1 while arr[cur] < arr[left_most]: water += arr[left_most] - arr[cur] cur+=1 left_most = cur # 右边界为短板,同上一样的算法 else: cur = right_most-1 while arr[cur] < arr[right_most]: water += arr[right_most] - arr[cur] cur -= 1 right_most = cur return water
# -*- coding:utf-8 -*- def max_yu(list_yu): max_n = 0 i = 0 max_zhu_inedx = [] len_n = len(list_yu) max_zhu = max(list_yu) max_zhu_wzhi_c = list_yu.index(max_zhu) max_zhu_count = list_yu.count(max_zhu) if max_zhu_count == 1 and list_yu.count(list_yu[0]) == len_n-1: print(max_n) return max_n else: if max_zhu_count > 1: while i < len_n: if max_zhu == list_yu[i]: max_zhu_inedx.append(i) i += 1 min_zhu_index = min(max_zhu_inedx) max_zhu_index = max(max_zhu_inedx) if max_zhu_index - min_zhu_index == 1: max_n = 0 else: min_zhu_index_lshi = min_zhu_index while min_zhu_index_lshi < max_zhu_index: max_n = max_n + max_zhu - list_yu[min_zhu_index_lshi] min_zhu_index_lshi += 1 chushi = max_zhu_index while chushi < len_n: max_f1_list = list_yu[chushi + 1:] if len(max_f1_list) != 0: max_f1 = max(max_f1_list) max_f1_inedx = max_f1_list.index(max_f1) if max_f1_inedx == 0: chushi += 1 else: j = 0 while j < max_f1_inedx: max_n = max_n + max_f1 - max_f1_list[j] j += 1 chushi = max_f1_inedx + 1 + chushi else: chushi += 1 chushi = min_zhu_index while chushi > 0: max_f2_list = list_yu[:chushi] max_f2 = max(max_f2_list) max_f2_inedx = max_f2_list.index(max_f2) if max_f2_inedx == len(max_f2_list) - 1: chushi -= 1 else: j = max_f2_inedx while j < len(max_f2_list): max_n = max_n + max_f2 - max_f2_list[j] j += 1 chushi = max_f2_inedx return max_n else: max_zhu_inedx.append(max_zhu_wzhi_c) if len(max_zhu_inedx) == 1: chushi = max_zhu_wzhi_c while chushi < len_n: max_f1_list = list_yu[chushi+1:] if len(max_f1_list) != 0: max_f1 = max(max_f1_list) max_f1_inedx = max_f1_list.index(max_f1) if max_f1_inedx == 0: chushi += 1 else: j = 0 while j < max_f1_inedx: max_n = max_n + max_f1 - max_f1_list[j] j += 1 chushi = max_f1_inedx + 1 + chushi else: chushi += 1 chushi = max_zhu_wzhi_c while chushi > 0: max_f2_list = list_yu[:chushi] max_f2 = max(max_f2_list) max_f2_inedx = max_f2_list.index(max_f2) if max_f2_inedx == len(max_f2_list) - 1: chushi -= 1 else: j = max_f2_inedx while j < len(max_f2_list): max_n = max_n + max_f2 - max_f2_list[j] j += 1 chushi = max_f2_inedx return max_n max_yu([3,1,2,5,2,4] )
class Solution: def trap(self, height: List[int]) -> int: #双指针优化 s,left_wall,right_wall=0,0,0 left,right=0,len(height)-1 while left<right: left_wall=max(left_wall,height[left]) right_wall=max(right_wall,height[right]) if left_wall<right_wall: s+=left_wall-height[left] left+=1 else: s+=right_wall-height[right] right-=1 return s #暴力解法 # s=0 # for i in range(1,len(height)-1): # if min(max(height[:i]),max(height[i+1:]))>height[i]: # v=min(max(height[:i]),max(height[i+1:]))-height[i] # s+=v # return s #转换为一个类似岛屿问题时间超过限制 # m=max(height) # n=len(height) # v=0 # dp=[[0]*n for _ in range(m)] # for i in range(m): # dp[i][0]=0 # dp[i][n-1]=0 # for i in range(m): # for j in range(1,n-1): # if height[j]<m-i and height[j]<=max(height[j+1:]) and ((height[j]<=height[j-1] and height[j-1]>=m-i)&nbs***bsp;dp[i][j-1]==1) and max(height[j+1:])>=m-i: # dp[i][j]=1 # v+=1 # else: # dp[i][j]=0 # return v
class Solution: def maxWater(self , arr ): # write code here start = arr[0] end = arr[-1] top = max(arr) n = len(arr) water = n*top-sum(arr) for i in range(n): if arr[i] < top and arr[i] <=start: water -= top-start elif arr[i] < top and arr[i] > start: start = arr[i] water -= top - start elif arr[i] == top: break for j in reversed(range(n)): if arr[j] < top and arr[j] <=end: water -= top-end elif arr[j] < top and arr[j] > end: end = arr[j] water -= top - end elif arr[j] == top: break return water
class Solution: def maxWater(self , arr ): # write code here cnt, left, right = 0, 0, len(arr)-1 while left < right: minn = min(arr[left], arr[right]) while left < right and arr[left] <= minn: cnt += minn - arr[left] left += 1 while left < right and arr[right] <= minn: cnt += minn - arr[right] right -= 1 return cnt
# # max water # @param arr int整型一维数组 the array # @return long长整型 # class Solution: def maxWater(self , arr ): top = arr.index(max(arr)) list_1 = arr[0:top+1] list_2 = arr[top::] list_2 = list_2[::-1] list_s = [list_1,list_2] num_c = 0 for elist in list_s: num_s = elist[0] for i in range(len(elist)): if 0<i<len(elist)-1: num_e = elist[i] if num_s > num_e: num_c += num_s-num_e else: num_s = num_e return num_c