zoukankan      html  css  js  c++  java
  • 42. Trapping Rain Water

    https://leetcode.com/problems/trapping-rain-water/#/solutions

    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!

     Fb: O(1)space

    这种方法是基于动态规划的,基本思路就是维护一个长度为n的数组,进行两次扫描,一次从左往右,一次从右往左。第一次扫描的时候维护对于每一个bar左边最大的高度是多少,存入数组对应元素中,第二次扫描的时候维护右边最大的高度,并且比较将左边和右边小的最大高度(我们成为瓶颈)存入数组对应元素中。这样两遍扫描之后就可以得到每一个bar能承受的最大水量,从而累加得出结果。这个方法只需要两次扫描,所以时间复杂度是O(2*n)=O(n)。空间上需要一个长度为n的数组,复杂度是O(n)。代码如下:

    常规做法:

    public int trap(int[] height) {
            int[] A = height;
            if(A==null || A.length==0)  
            return 0;  
            int max = 0;  
            int res = 0;  
            int[] container = new int[A.length];  
            for(int i=0;i<A.length;i++) {  
            
                max = Math.max(max,A[i]); 
                container[i]=max;  
            }  
            max = 0;  
            for(int i=A.length-1;i>=0;i--) {  
                max = Math.max(max,A[i]); 
                container[i] = Math.min(max,container[i]);  
             
                res += container[i]-A[i]>0?container[i]-A[i]:0;  
            }      
            return res;       
        }
    

      

    Here is my idea: instead of calculating area by height*width, we can think it in a cumulative way. In other words, sum water amount of each bin(width=1).
    Search from left to right and maintain a max height of left and right separately, which is like a one-side wall of partial container. Fix the higher one and flow water from the lower part. For example, if current height of left is lower, we fill water in the left bin. Until left meets right, we filled the whole container.

     左右指针、最大值维护、正序、逆序

    public int trap(int[] A){
        int a=0;
        int b=A.length-1;
        int max=0;
        int leftmax=0;
        int rightmax=0;
        while(a<=b){
            leftmax=Math.max(leftmax,A[a]);
            rightmax=Math.max(rightmax,A[b]);
            if(leftmax<rightmax){
                max+=(leftmax-A[a]);       // leftmax is smaller than rightmax, so the (leftmax-A[a]) water can be stored
                a++;
            }
            else{
                max+=(rightmax-A[b]);
                b--;
            }
        }
        return max;
    }
    

      

      

  • 相关阅读:
    Ui——创建视图的方法及过程
    iOS设计模式----原型模式
    浅谈OC中排序的方法
    Solid Dominoes Tilings (轮廓线dp打表 + 容器)
    Shell Necklace (dp递推改cdq分治 + fft)
    Rigid Frameworks (画图二分图规律 + DP + 数学组合容斥)
    PowMod (欧拉推式子 + 指数循环节)
    Necklace (全排列 + 匈牙利)
    GCD (RMQ + 二分)
    Game (思维)
  • 原文地址:https://www.cnblogs.com/apanda009/p/7115984.html
Copyright © 2011-2022 走看看