---
# System prepended metadata

title: 42. Trapping Rain Water
tags: [pointer, Leetcode, python, array, Top 100 Liked Questions, hard]

---

###### 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)

```