描述
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例1
输入:
[3,1,2,5,2,4]
返回值:
5
说明:
数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水
示例2
输入:
[4,5,1,3,2]
返回值:
2
这道题的重点是,不能只看局部的低谷,要看整体的低谷。我一开始直接找山谷区进行加和,后来发现自己错了。
有两种情况:
1.首先向左找到一个递减序列,以该值作为木桶的左木板,之后继续向右找到第一个大于左木板的值作为右木板,就是一个完整的木桶。
2.和1相同,只是变成向右找
这是因为假设序列:10 1 2 1 9; 如果找局部山谷,就会变成10 1 2; 2 1 9;而少了非常多的水。为什么要分两种情况呢,因为如果按情况1来找,10 1 2 1 9会变成找不到大于左木板的值,假设这个序列是10 1 2 1 9 1,会导致少算很多水。故用双指针一同从两边开始找,找到两个指针相撞为止,即可解决该问题
#
# max water
# @param arr int整型一维数组 the array
# @return long长整型
#
def getWater(left, right ,arr):
if left >= right:
return 0
water = 0
short = min(arr[left], arr[right])
for k in range(left + 1, right):
water += short - arr[k]
return water
class Solution:
def maxWater(self , arr ):
water, l = 0, len(arr)
i, j = 0, l - 1
while i < j:
while i < j and arr[i] <= arr[i+1]:
i = i + 1
while i < j and arr[j] <= arr[j-1]:
j = j - 1
left = i
right = j
i = i + 1
j = j - 1
while i < j and arr[i] < arr[left]:
i = i + 1
while i < j and arr[j] < arr[right]:
j = j - 1
if i < j:
water += getWater(left, i, arr)
water += getWater(j, right ,arr)
else:
water += getWater(left, right, arr)
return water
# write code here