zoukankan      html  css  js  c++  java
  • 【42. 接雨水】【困难】【思维】

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

    示例:

    输入: [0,1,0,2,1,0,1,3,2,1,2,1]
    输出: 6
    【分析】:一般情况下,如果按照人的思维方式的话,要看每一个位置可以蓄多少水,我们首先会看看,左边最高的柱子有多高(这里的左边最高还包括当前这个位置的,不是真的就是在左边的最高的柱子),右边的柱子最高的有多高,然后取他们两个当中的最小值,减去当前柱子的高度,就是这个位置可以蓄的水的量了。


    class Solution {
        public int trap(int[] height) {
            if(height == null || height.length == 0) return 0;
            int n = height.length;
            int tmp, res = 0;
            int maxLeft = 0, maxRight = 0;
            int[] left = new int[n];
            int[] right = new int[n];
            for(int i=0; i<n; i++){
                left[i] = maxLeft;
                maxLeft = Math.max(maxLeft, height[i]);
            }
            for(int i=n-1; i>=0; i--){
                right[i] = maxRight;
                maxRight = Math.max(maxRight, height[i]);
            }
            for(int i=0; i<n; i++){
                tmp = Math.min(left[i],right[i]);
                if(tmp >= height[i]){
                    res += (tmp - height[i]);
                }
            }
            return res;
        }
    }
    

    [双指针法]:
    而这个two pointer的算法就是,为什么非要把两边的最高的柱子都找出来再找短板呢?我们直接找短板不就好了。
    为什么这样行得通呢?
    因为你想啊,左边一个值记录到当前位置为止左边最高的柱子,右边一个值记录到当前位置为止右边最高的柱子,假设我们知道右边这个最高的柱子比左边那个最高的柱子矮,那么在当前位置,这个比较矮的右边最高柱一定是当前位置的短板,为什么呢?因为这个右边最高柱已经比那个左边最高柱矮了,那么即便两个
    pointer 中间还有没有走完的位置,当前位置的长板也大于等于那个没有走完的左边最高柱了。所以我们就证明了,这个比较矮的板是当前位置的短板,然后用短板值减去当前柱子的高度就是当前位置蓄水量了。

    整个vector扫一遍就是o(n)时间复杂度,左边一个pointer,右边一个pointer,还有两个值分别记录左边最高柱、右边最高柱,还有一个值记录蓄水量。所以是o(1)空间复杂度。

    时间复杂度分析:o(n)

    
    class Solution {
        public int trap(int[] height) {
            if(height == null || height.length == 0) return 0;
            int n = height.length;
            int l = 0, r = n-1;
            int res = 0;
            int maxL = 0, maxR = 0;
            while(l < r){
                maxL = Math.max(maxL, height[l]);
                maxR = Math.max(maxR, height[r]);
                if(maxL < maxR){
                    res += maxL - height[l++];
                }else{
                    res += maxR - height[r--];
                }
            }
            return res;
        }
    }
    
  • 相关阅读:
    2019年年终总结
    [转]网络基本功08-细说TCP滑动窗口
    anaconda启动报错-pythonw.exe
    FRP+WoL实现远程开机+远程桌面
    [转]网络基本功06-链路聚合
    我的效率工具分享
    比海飞丝更柔顺的写作体验
    阿里云加Picgo或MPic搭建最豪横的图床
    markdown从入门到放弃word和PDF
    Pocket+Evernote 打造个人知识库体系
  • 原文地址:https://www.cnblogs.com/Roni-i/p/10915714.html
Copyright © 2011-2022 走看看