• 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

  • 相关阅读:
    avalon做的抽奖效果
    [转]谈谈前端渲染 VS 后端渲染
    迷你MVVM框架 avalonjs 1.3.7发布
    迷你MVVM框架 avalonjs 学习教程22、avalon性能大揭密
    Facebook React 和 Web Components(Polymer)对比优势和劣势
    迷你MVVM框架 avalonjs 学习教程21、双向绑定链
    迷你MVVM框架 avalonjs 学习教程20、路由系统
    html中的数据岛:利用DSO和javascript在html中动态加载和浏览xml数据
    使用JS的 FileReader 读取本地文本文件(可兼容各种浏览器)
    简易版jquery
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4436338.html
Copyright © 2020-2023  润新知