Trapping Rain Water

LeetCode problem 42. Trapping Rain Water.

## Problem description

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.

Example 1
**Input:** height = [0,1,0,2,1,0,1,3,2,1,2,1]
**Output:** 6
**Explanation:** The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

Example 2
**Input:** height = [4,2,0,3,2,5]
**Output:** 9
Constraints
* `n == height.length`
* `0 <= n <= 3 * 104`
* `0 <= height[i] <= 105`

## Problem analysis

This problem can be solved using **two pointers**, by starting from both ends of the input data, and moving the pointers step by step, until the `left` and `right` pointers meet together.

**So how do we know that where we can trap water, and how much water can be trapped at each position?**

We are able to see that the input data may contain **peaks** and **valleys**, and obviously rain water can only be trapped inside valleys.

* A **valley** is a subarray `[l..r]` in the input data such that, for every position *i* in the subarray, the conditions `height[i] < height[l-1]` and `height[i] < height[r-1]` are both satisfied.
* A **peak** is a subarray `[l..r]` in the input data such that every element has the same height *h*, and the conditions `h > height[l-1]` and `h > height[r-1]` are both satisfied.
	+ Note that a peak may be part of a valley. But this is irrelevant to problem solving, since there will be water filling up above this peak, and the water height is constrained by the lower height at either end of the valley.

Now for any interval `[l..r]`, there may be three cases in terms of the number of valleys:

1. No valley. The interval may be flat or monotonically increasing / decreasing, so it cannot trap any rain water at all.
2. One valley. All positions between *l* and *r* (not including *l* and *r*) will trap rain water.
3. Two or more valleys. The interval can be further divided into sub-intervals such that each interval contains one valley.

For each valley `[l..r]`, at each single position *i* (*excluding both ends*) the water amount is `min(lh, rh) - i`, where *lh* and *rh* are the *constraining heights* on left and right respectively, i.e. `lh = height[l]` and `rh = height[r]`.

So the overall procedure to compute the total amount of rain water is as follows:

1. Initialize `left = 0`, `right = height.length - 1`, `lh = height[left]`, `rh = height[right]`, `total = 0`.
2. While `left < right`:
	1. Always pick the pointer that is pointing to a lower height. Or if `height[left] == height[right]`, we choose to move the left pointer (it doesn't matter to move either one in this case). If picked `left`, then move `left` to the right by 1 step. Otherwise, move `right` to the left by 1 step.
			+ If `height[left] < lh`, then the position will capture `lh - height[left]` units of water. Add the amount to `total`.
			+ Otherwise the position `left` cannot be used to trap water, but may become a constraining height instead in the future. So set `lh = height[left]`.
		* Similarly, if moved the `right` pointer:
			+ If `height[right] < rh`, then the position will capture `rh - height[right]` units of water. Add the amount to `total`.
			+ Otherwise the position `right` cannot be used to trap water, but may become a constraining height instead in the future. So set `rh = height[right]`.
3. After the two pointers meet, i.e. `left == right`, return `total`.

### Complexity analysis

Time complexity
Since we move the pointers `left` and `right` until the two pointer meet, and within each iteration there is O(1) amount of computation, the total time complexity is **O(n)**, where *n* is the number of inputs.
Space complexity
Since we did not allocate additional data structures, the space complexity is **O(1)**.
## Solutions

### C++ solution

```
class Solution {
public:
 int trap(std::vector<int>& height) {
 const int len = height.size();
 if (len <= 2) {
 return 0;
 }

 int total = 0;

 // use two pointers
 int left = 0, right = len - 1;
 int lh = height[left], rh = height[right];
 while (left < right) {
 if (lh < rh) {
 // move left pointer
 ++left;

 // avoid double computation of water amount
 // at the same position
 if (left == right) {
 break;
 }

 // water amount is constrained by the left block's height
 if (height[left] < lh) {
 total += lh - height[left];
 }
 else {
 lh = height[left];
 }
 }
 else {
 // move right pointer
 --right;

 // avoid double computation of water amount
 // at the same position
 if (left == right) {
 break;
 }

 // water amount is constrained by the right block's height
 if (height[right] < rh) {
 total += rh - height[right];
 }
 else {
 rh = height[right];
 }
 }
 }

 return total;
 }
};

```

### Java solution

```
class Solution {
 public int trap(int[] height) {
 final int len = height.length;
 if (len <= 2) {
 return 0;
 }

 int total = 0;

 // use two pointers
 int left = 0, right = len - 1;
 int lh = height[left], rh = height[right];
 while (left < right) {
 if (lh < rh) {
 // move left pointer
 ++left;

 // avoid double computation of water amount
 // at the same position
 if (left == right) {
 break;
 }

 // water amount is constrained by the left block's height
 if (height[left] < lh) {
 total += lh - height[left];
 }
 else {
 lh = height[left];
 }
 }
 else {
 // move right pointer
 --right;

 // avoid double computation of water amount
 // at the same position
 if (left == right) {
 break;
 }

 // water amount is constrained by the right block's height
 if (height[right] < rh) {
 total += rh - height[right];
 }
 else {
 rh = height[right];
 }
 }
 }

 return total;
 }
}

```