42. 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 is able to trap after raining.

For example, 
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

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!

链接: http://leetcode.com/problems/trapping-rain-water/

题解:

经典题目接雨水。对每个index单独进行考虑,则这个index左侧最高bar与右侧最高bar能组成一个容器,在这个容器里,左侧bar和右侧bar中较低的一个与当前index的差值就为当前index所能储存的雨水量。

Time Complexity - O(n), Space Complexity - O(n)。  可以只使用一个数组,但不如下面代码看起来思路清晰。另外有stack和双指针法,还有待了解。

public class Solution {
    public int trap(int[] height) {                 //dp
        if(height == null || height.length == 0)
            return 0;
        int[] forward = new int[height.length];
        int[] backward = new int[height.length];
        int[] res = new int[height.length];
        
        int leftBar = height[0];
        
        for(int i = 1; i < height.length - 1; i++) {
            forward[i] = leftBar;
            leftBar = Math.max(height[i], leftBar);
        }
        
        int rightBar = height[height.length - 1];
        
        for(int i = height.length - 2; i >= 0; i--) {
            backward[i] = rightBar;
            rightBar = Math.max(height[i], rightBar);
        }
        
        int max = 0;
        
        for(int i = 1; i < height.length - 1; i++) {
            int curVolume = Math.min(forward[i], backward[i]) - height[i];
            if(curVolume > 0)
                max += curVolume;
        }
        
        return max;
    }
}

 

二刷:

这道题现在很熟悉了。就是记忆一下左边最大的leftBar,遍历一遍数组。再记忆一下右边最大的rightBar,遍历一遍数组。最后从 i = 1到i = height.length - 2,计算volumn = Math.min(leftBar, rightBar)  - height[i],假如这个volumn大于等于0,则这个点的雨水可以被接,我们把这个volumn加入到最终结果中。

仔细查看了Discuss发现还有Space Complexity O(1)的解法。研究一下, 代码主要来自discuss里面的mcrystal,分为下面几个步骤

  1. 像Container with most water一样,设立一个lo = 0, hi = height.length - 1,使用双指针来夹逼遍历。
  2. 设立一个res = 0, maxLeftBar = 0, maxRightBar = 0
  3. 在 lo <= hi的条件下进行遍历
    1. 假如height[lo] <= height[hi],或者height[lo] < height[hi]也可以, 这时候说明当前左边的height <= 右边的height。那么我们只需要考虑左边界和当前左边的height的差值,这个差值就是我们能容纳多少水
      1. 在上述情况下,假如height[lo] >= maxLeftBar, 当前index的值 > maxLeftBar,那么我们不能接到水,我们要把maxLeftBar更新为height[lo]
      2. 否则res += maxLeftBar - height[lo],我们把这个差值加入到结果中
      3. lo++
    2. 否则,左边的当前height > 右边的当前height,容易能盛多少水取决于右边的height以及maxRightBar的差值
      1. 当height[hi] >= maxRightBar,我们更新maxRightBar = height[hi]
      2. 否则,我们把结果 maxRightBar - height[hi]加入到res中
      3. hi--
  4. 最后返回结果res就可以了, 很巧妙。

Java:

Time Complexity - O(n), Space Complexity - O(n)

public class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int n = height.length;
        int[] leftBars = new int[n];
        int maxLeftBar = height[0];
        for (int i = 1; i < height.length; i++) {
            leftBars[i] = maxLeftBar;
            maxLeftBar = Math.max(maxLeftBar, height[i]);
        }
        
        int[] rightBars = new int[n];
        int maxRightBar = height[height.length - 1];
        for (int i = height.length - 2; i >= 0; i--) {
            rightBars[i] = maxRightBar;
            maxRightBar = Math.max(maxRightBar, height[i]);
        }
        
        int res = 0;
        for (int i = 1; i < height.length - 1; i++) {
            int volumn = Math.min(leftBars[i], rightBars[i]) - height[i];
            if (volumn > 0) {
                res += volumn;
            }
        }
        
        return res;
    }
}

 

Time Complexity - O(n), Space Complexity - O(1)

public class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int lo = 0, hi = height.length - 1;
        int maxLeftBar = 0, maxRightBar = 0;
        int res = 0;
        while (lo <= hi) {
            if (height[lo] <= height[hi]) {
                if (height[lo] >= maxLeftBar) {
                    maxLeftBar = height[lo];
                } else {
                    res += maxLeftBar - height[lo];
                }     
                lo++;
            } else {
                if (height[hi] >= maxRightBar) {
                    maxRightBar = height[hi];
                } else {
                    res += maxRightBar - height[hi];
                }
                hi--;
            }
        }
        return res;
    }
}

 

三刷:

Java:

1D dp: - Time Complexity - O(n), Space Complexity - O(n)

public class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) return 0;
        int len = height.length;
        int[] leftVolumns = new int[len];
        
        int localMaxVol = height[0];
        for (int i = 1; i < len - 1; i++) {
            leftVolumns[i] = localMaxVol;
            localMaxVol = Math.max(localMaxVol, height[i]);
        }
        
        localMaxVol = height[len - 1];
        int res = 0;
        for (int i = len - 1; i > 0; i--) {
            int curVolumn = Math.min(leftVolumns[i], localMaxVol) - height[i];
            if (curVolumn > 0) res += curVolumn;
            localMaxVol = Math.max(localMaxVol, height[i]);
        }
        
        return res;
    }
}

 

2-pointers: - Time Complexity - O(n), Space Complexity - O(1)

public class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) return 0;
        int len = height.length;
        int lo = 0, hi = len - 1, maxLeftBar = 0, maxRightBar = 0;
        int res = 0;
        
        while (lo <= hi) {
            if (height[lo] <= height[hi]) {
                if (height[lo] < maxLeftBar) {
                    res += maxLeftBar - height[lo];
                } else {
                    maxLeftBar = height[lo];
                }
                lo++;
            } else {
                if (height[hi] < maxRightBar) {
                    res += maxRightBar - height[hi];
                } else {
                    maxRightBar = height[hi];
                }
                hi--;
            }
        }
        
        return res;
    }
}

 

 

Reference: 

http://www.cnblogs.com/springfor/p/3877101.html

https://leetcode.com/discuss/16171/sharing-my-simple-c-code-o-n-time-o-1-space

https://leetcode.com/discuss/10046/share-my-short-solution

https://leetcode.com/discuss/45812/7-lines-c-c

https://leetcode.com/discuss/45791/8-lines-c-c-java-python-solution

https://leetcode.com/discuss/27973/concise-o-1-space-java-solution

 

posted @ 2015-04-17 23:22  YRB  阅读(409)  评论(0编辑  收藏  举报