leetcode42 - Trapping Rain Water - hard

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.

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 Marcosfor contributing this image!
 
 
 

问题转换:每个point能存多少水,取决于向左看全局最高点比我高多少,以及向右看全局最高点比我高多少,这两者中的较小值就是我当前的蓄水值。

法1:两遍扫描存数组。O(2n), O(n)。left[]+max值记录从左边开始,每个点当前从左边开始遇到的最大值比我高多少。right[]+max值记录从右边开始,每个点从右边开始遇到的最大值比我高多少。最后再扫描一遍取较小值加到ans里(或者这个扫描可以合并到第二次里)。

法2:双指针。O(n),O(1)。left,right指针活动, leftMax, rightMax记录左右当前遇到的最高点。根据上面的图可以感受到,每个点只取决于左右最高点中的短板,所以每次对比leftMax, rightMax找到短板是哪边后,就移动那边的指针。然后对比当前遇到的数字和短板的差距,可以蓄水就加到答案里,同时更新最高点的高度。

 

实现1:

class Solution {
    public int trap(int[] height) {
        int max = 0;
        int[] left = new int[height.length];
        int[] right = new int[height.length];
        for (int i = 0; i < height.length; i++) {
            left[i] = height[i] < max ? max - height[i] : 0;
            max = Math.max(max, height[i]);
        }
        max = 0;
        for (int i = height.length - 1; i >= 0; i--) {
            right[i] = height[i] < max ? max - height[i] : 0;
            max = Math.max(max, height[i]);
        }
        int ans = 0;
        for (int i = 0; i < height.length; i++) {
            ans += Math.min(left[i], right[i]);
        }
        return ans;
    }
}

 

实现2:

class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int left = 0, right = height.length - 1;
        int left_max = height[left], right_max = height[right];
        int ans = 0;
        
        while (left < right) {
            if (left_max <= right_max) {
                left++;
                if (height[left] < left_max) {
                    ans += (left_max - height[left]);
                }
                left_max = Math.max(left_max, height[left]);
                
            } else {
                right--;
                if (height[right] < right_max) {
                    ans+= (right_max - height[right]);
                }
                right_max = Math.max(right_max, height[right]);
            }
        }
        return ans;
    }
}

 

posted @ 2018-09-15 11:01  jasminemzy  阅读(156)  评论(0编辑  收藏  举报