給定 n 個非負整數表示每一個寬度爲 1 的柱子的高度圖,計算按此排列的柱子,下雨以後能接多少雨水。數組
上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種狀況下,能夠接 6 個單位的雨水(藍色部分表示雨水)。 感謝 Marcos 貢獻此圖。spa
示例:指針
輸入: [0,1,0,2,1,0,1,3,2,1,2,1] 輸出: 6
最簡單的想法:對於每一個元素都要考慮它能接多少雨水:code
第一個元素是0,能接0雨水blog
第二個元素是1,能接0雨水io
第三個元素是0,能接1雨水class
...方法
第六個元素是0,能接2雨水。im
能夠看到,每一個元素能接的雨水量是:當前位置左邊最高的數與右邊最高的數的最小值減去當前位置的數。總結
例如第六個元素接水量爲2 = min(2,3)-0=2。
總結:對於每一個位置,都考慮其左邊最高的牆和右邊最高的牆便可。
思路圖:
1 class Solution: 2 def trap(self, height): 3 if not height: return 0 4 n = len(height) 5 left,right = [0]*n, [0]*n # 每一個位置都存放其左邊最大值和右邊最大值 6 temp = 0 7 for i in range(n): 8 temp= max(temp,height[i]) # 找每一個元素的左邊最大值(含自身) 9 left[i] = temp 10 temp = 0 11 for i in range(n-1,-1,-1): 12 temp = max(temp,height[i]) # 找每一個元素的右邊最大值(含自身) 13 right[i] = temp 14 res = 0 15 for i in range(n): 16 res+=min(left[i],right[i])-height[i] # 最小的高度值-自身 17 return res
方法2. 雙指針法
仍是一個思路:當前位置須要左右兩堵牆的最小值減去當前值。
左右兩端各設定一個指針,初始兩堵牆。若是左端小於右端,則以右端爲牆,當前值等於左牆和右牆的最小值減去當前值。
1 class Solution: 2 def trap(self, height): 3 if not height: return 0 4 5 left, right = 0 , len(height)-1 # 左右指針 6 area = 0 7 leftwall, rightwall = 0,0 # 左牆和右牆 8 while(left<right): 9 if height[left]<height[right]: # 右邊高,則以右端爲牆 10 if leftwall>height[left]: # 若是左牆也比當前位置高的話 11 area+=min(leftwall,height[right])-height[left] # 面積就是兩牆最低者減去當前位置的高度 12 else: 13 leftwall = height[left] # 不然更新左牆 14 left+=1 15 else: 16 if rightwall>height[right]: 17 area+=min(rightwall,height[left])-height[right] 18 else: 19 rightwall = height[right] 20 right-=1 21 return area