Leetcode 42. Trapping Rain Water

42 Trapping Rain Water

1 Problem:

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

在这里插入图片描述

The above elevation map 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. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

2 Analysis

Note: Part I is my own thinking which can be a little dumb, while easy to think. The analysis for optimal solution is in Part II.

Part I

Just like a bucket, in which the shortest stripe of wood decides the capacity of the bucket. In this problem, if we want to trap water, basically we need two bars to form an interval, and the capacity depends on the height of the lower bar.

在这里插入图片描述

To solve this problem, we can try to look at these bars one by one from left to right. Start with a bar, denoting it as “current”, if we find a another bar on the right which is higher than or equal to this one, then the water will be trapped. The higher bar that we find now becomes “current”, and we continues to find the next bar higher than “current”. By doing this repeatedly from the left to the right, we find part of the solution, as is shown in the following figure.
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Notice that we have searched from left to right. Similarly, this rule also applies from right to left. As is shown below. It is worth noting that the “higher” here has the same height with the “current”, the situation of which also traps water.

在这里插入图片描述

The last thing we should pay attention to is the problem of overlapping caused by going from left to right and going from right to left. This overlapping problem occurs when two bars have the same height. The following condition illustrates this issue clearly. The middle part is reconsidered when we go through from the second direction.

在这里插入图片描述
The method to avoid this issue is rather simple. When going from another direction, we simply stop at the highest bar computed before.

Part II

The optimal solution search from both direction at the same time. Use two indices to record the left position and right position, as is shown below.

Also, we need to use maxleft and maxright to record the highest bar we come across so far from left and right respectively. This value will be used for computing the amount of water trapped in a position.

The key idea is that by comparing the left bar and right bar, we find a relatively higher one between these two bars. This ensures that there will be a higher or equal bar in another side, which allows us to calculate the trapped capacity from the lower side.
在这里插入图片描述

As for how to compute how much water is trapped, we need to compute bar by bar. For example, if the the height of the current bar is less than max value in this side, the amount of water trapped in this position should be added to the total amount.

As the “left” increases and “right” decreases, they will meet at some point and we get the total amount of trapped water.

3 Implementation in C++

  • First try: An acceptable solution
class Solution {
public:
    int trap(vector<int>& height) {
        
        if (height.size() == 1 || height.empty())
            return 0;
        
        int current, higher, trapped;
        current = higher = 0;
        trapped = 0;     
        
         // from left to right
        while(height[current] == 0)
            current++;
        for (int i = current+1; i < height.size(); i++){
            
            // find higher bar 
            if ( i-current > 0 && height[i] >= height[current]){     
                higher = i;
                // compute area bar by bar between the region 
                for (int j = current+1; j < higher; j++)
                    trapped = trapped + height[current]- height[j];
                current = higher;
            }    
        }
        
        int end = higher;
        // from right to left 
        current = higher = height.size()-1;
        while(height[current] == 0)
            current--;
        for (int i = current+1 ; i >=end ; i--){
            
            // find higher bar 
            if (current-i > 0 && height[i] >= height[current]){       
                // update higher 
                higher = i;
                // compute area 
                for (int j = current-1; j > higher; j--)
                    trapped = trapped + height[current]- height[j];
                current = higher;
            }
        }
        return trapped;
    }
};
  • The optimal solution: two pointers method
class Solution{
public:
    int trap(vector<int>& height){
        
        int left, right, trapped;
        left = 0;
        right = height.size()-1;
        trapped = 0;
        
        int maxleft = 0, maxright = 0;
        
        while(left <= right){
            
            if (height[left] <= height[right]){
                
                if (height[left] >= maxleft)
                    maxleft = height[left];
                else
                    trapped = trapped + maxleft - height[left];
                left++;
            }
            else{
                if (height[right] >= maxright)
                    maxright = height[right];
                else
                    trapped = trapped + maxright - height[right];
                right--;
            }
        }
        return trapped;
    }
};
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读