###### tags: `Leetcode` `hard` `pointer` `array` `python` `Top 100 Liked Questions` # 42. Trapping Rain Water ## [題目來源:] https://leetcode.com/problems/trapping-rain-water/ ## 題目: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining. ![](https://i.imgur.com/4XwjQqk.png) ###### [圖片來源:]https://leetcode.com/problems/trapping-rain-water/ ## 解題想法: * 法1: 考慮每個位置pox可以增加的容量 * 取pos左邊最高與po右邊最高位置 * 兩者取較小的 * 最終減去pos本身,即為該pos可增加的容量 1. 從左向右,求每個位置的左邊最高位置 2. 從右向左,求每個位置的右邊最高位置 3. 最終再遍歷,累加每點的容量 ## Python (法1: O(n) ): ``` python= class Solution(object): def trap(self, height): """ :type height: List[int] :rtype: int """ if not height: return 0 n=len(height) res=0 left_max=[0]*(n) right_max=[0]*(n) #求左邊最大 從左->右遍歷 left_max[0]=height[0] #最左邊設為初始 for i in range(1,n): #每次比較前一個left_max與當下自己的值 left_max[i]=max(left_max[i-1],height[i]) #求右邊最大 從右->左遍歷 right_max[-1]=height[-1] #最右邊設為初始 for i in range(n-2,-1,-1): right_max[i]=max(right_max[i+1],height[i]) #求每點可增加值 並累加 for i in range(n): res+=min(left_max[i],right_max[i])-height[i] return res result=Solution() ans=result.trap(height = [0,1,0,2,1,0,1,3,2,1,2,1]) print(ans) ``` * 法2: 使用兩個pointer,head、tail分別指向左右兩端,再設兩個left_max、right_max紀錄左右邊目前最大值 * 每次比較height[head]、height[tail]大小 * if height[head]<height[tail],表示左邊小 * 則再比較height[head]與left_max * 若left_max>height[head],表示其差值為height[head]可以增加的容量 * 若left_max<height[head],則left_max換人當 ## Python (法2: O(n) ): ``` python= class Solution(object): def trap(self, height): """ :type height: List[int] :rtype: int """ if not height: return 0 head=0 tail=len(height)-1 left_max=0 #記錄左邊最大 right_max=0 #記錄右邊最大 res=0 while head<tail: if height[head]<height[tail]: #左邊小 if height[head]<left_max: res+=left_max-height[head] else: left_max=height[head] head+=1 else: #右邊小 if height[tail]<right_max: res+=right_max-height[tail] else: right_max=height[tail] tail-=1 return res result=Solution() ans=result.trap(height = [0,1,0,2,1,0,1,3,2,1,2,1]) print(ans) ```