Leetcode42. Trapping Rain Water

关键词:DP,stack,2pointer

首先是暴力解法:

class Solution {
    public int trap(int[] height) {
        int leftmax = 0;
        int rightmax = 0;
        int ans=0;
        for(int i=0;i<height.length;i++){
            leftmax=0;rightmax=0;
            int tempmax=0,p=i;
            if(i>0){
                p=i-1;tempmax=0;
                while(p>=0){
                    tempmax = Math.max(tempmax,height[p--]);
                }
                leftmax=tempmax;
            }
            if(i<height.length-1){
                p=i+1;tempmax=0;
                while(p<=height.length-1){
                    tempmax = Math.max(tempmax,height[p++]);
                }
                rightmax=tempmax;
            }
            if(rightmax>height[i]&&leftmax>height[i]){
                ans+=Math.min(rightmax,leftmax)-height[i];
            }
        }
        return ans;
    }
}

128ms , 2.99%。太垃圾了…不行。

然后看了discuss后思路2:

DP:用很简单的DP去处理左右的max的计算,存到数组里,这样只需遍历3遍,时间复杂度从O(n^2)降到了O(n)。

如:leftmax[i]表示,第i个元素左边最大的值。更新:leftmax[i]=max(leftmax[i-1],height[i-1])。

rightmax相同,然后再遍历一遍得到结果即可。

其实这道题并不难,自己开始的思路已经很接近了。

class Solution {
    public int trap(int[] height) {
        int[] leftmax = new int[height.length];
        int[] rightmax = new int[height.length];
        for(int i=1;i<height.length;i++){
            leftmax[i] = Math.max(leftmax[i-1],height[i-1]);
        }
        for(int i=height.length-2;i>=0;i--){
            rightmax[i] = Math.max(rightmax[i+1],height[i+1]);
        }
        int ans=0;
        for(int i=0;i<height.length;i++){
            if(rightmax[i]>height[i]&&leftmax[i]>height[i]) ans+=Math.min(leftmax[i],rightmax[i])-height[i];
        }
        return ans;
    }
}

17ms,20.66%。但是也并不快诶。

思路3,stack,也很巧妙,遇到这种两边夹逼的,也可以往stack上想。自己没完全搞明白,下面是个错误但是接近的答案:

class Solution {
    public int trap(int[] height) {
        if(height==null||height.length==0) return 0;
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        int ans=0;
        for(int i=1;i<height.length;i++){
            if(height[i]>height[stack.peek()]){
                int mid = stack.pop();
                if(!stack.empty()){
                    ans+=(Math.min(height[i],height[stack.peek()])-height[mid])*(i-stack.peek()-1);
                }else{
                    stack.push(mid);
                }
                stack.push(i);
            }else if(height[i]<height[stack.peek()]){
                stack.push(i);
            }
        }
        return ans;
    }
}
Your input
[0,1,0,2,1,0,1,3,2,1,2,1]
Output
3
Diff
Expected
6
还有思路4,two pointer,有空可以看看。
DP即可。stack更好,能用two pointer更更好。
posted @ 2018-12-28 19:45  大胖子球花  阅读(90)  评论(0)    收藏  举报