42. 接雨水

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

示例 1:

42. 接雨水

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105

解题思路:一开始想了一个很笨的方法,就是一个高度一个高度遍历上去,首先遍历height数组找到最高的列,然后从高度1到最高高度,进行遍历,在每个高度,确定最左端和最右端,这就是墙,然后中间的如果发现有空着的,那res就加一,空着的高度小于当前遍历到的高度h,这个思路原本是可行的,就是比较费时,在leetcode上通过了319/320个例子,功败垂成,代码如下:

class Solution {
    public int trap(int[] height) {
        int res = 0, len = height.length;
        if(len<3) return res;
        int mx = height[0];
        for(int h : height) mx = Math.max(mx, h);
        if(mx==1) return res;
        for(int i=1; i<=mx; i++){
            int left = 0, right = len - 1;
            while(left<len && height[left]<i) left++;
            while(right>0 && height[right]<i) right--;
            for(int k=left+1; k<right; k++){
                if(height[k]<i) res++;
            }
        }
        return res;
    }
}

后来参考了网上的题解,发现了一个相对简洁的方法,这里贴出来,首先就是用两个指针分别指向头尾端点,然后用其中的较小值作为桶的最低一块木板的高度,也就是中间的值都只能小于或等于这个值,如果发现小于等于这个值的数,就在res中加上二者的差值,并且指针前进(左指针向右,右指针向左);如果发现比这个值大的数,那就需要更新最低木板的高度,此时跳出上一步的while循环,继续从头开始,最后,直到两个指针相遇。

代码 t99 s14 java

class Solution {
    public int trap(int[] height) {
        int res = 0;
        int len = height.length, left = 0, right = len - 1;
        while(left<right){
            int mn = Math.min(height[left], height[right]);
            while(left<right  && height[left]<=mn){
                res += mn - height[left++];
            }
            while(left<right && height[right]<=mn){
                res += mn - height[right--];
            }
        }
        return res;
    }
}

参考资料

上一篇:42岁程序员面试,腾讯+字节+阿里面经真题汇总,逆袭面经分享


下一篇:动态规划——剑指 Offer 42. 连续子数组的最大和