leetcode刷题 42接雨水

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

解题思路:

        先取i号柱子和j号柱子(i<j)两根柱子,做以下假设:

        1.i号柱子和j号柱子之间的柱子的高度均比它们两根要小。

        2.i号柱子左边的柱子均比i号柱子低,或者j号柱子右边的柱子均比j号柱子高。

        设min{i,j}表示的是i和j号柱子中较低的那根柱子的高度,那么任取i和j中间的某个位置k(i<k<j),则k号位置能装的最大雨水量为min{i,j}-height[k]

        提示:之所以做假设2,是为了防止上图示例1中i=4,j=6的情况:

        height[4]=1,heifht[6]=1,height[5]=0。满足假设1,但5号位置能装的最大水量并非1-0=0,而是2,正是因为4号柱子左边有高于它的柱子,6号柱子右边同样有高于它柱子。        

        为了满足以上假设,可以这样寻找i和j的位置:

        设置两个指针left和right,先将left指向0,right从left+1的位置开始向右寻找,直到找到一个柱子的高度大于等于height[left](left就相当于上文中的i,right相当于j),之后便可以将left与right之间的位置尽量灌满水,然后令left=right,right=left+1,继续重复,直到right到达数组右边界。

        当上述过程结束后,我们就把(height[i]<=height[j])的情况都处理好了,但忽视了(height[i]>height[j])的情况,因此可以模仿上述的过程,从数组最右端开始寻找i和j:

        right指向height.length-1,left从right-1的位置开始向左寻找,直到找到一个柱子的高度大于等于height[right],之后便可以将left与right之间的位置尽量灌满水,然后令right=left,left=right-1,继续重复,直到left到达左边界。

        通过从左到右,和从右到左两次遍历height数字,便可以将水灌满。

代码如下:

    //从左到右装一次,再从右到左装一次
    int res=0;
    public int trap(int[] height) {
        //从左到右
        int left=0,right=1;
        for (; right <height.length ; right++) {
            if(height[left]>height[right]) continue;
            updataLeft(height,left,right);
            left=right;
        }

        //从右到左
        right=height.length-1;
        left=right-1;
        for (; left>=0; left--) {
            if(height[left]<height[right]) continue;
            updataRight(height,left,right);
            right=left;
        }
        return res;
    }

    private void updataRight(int[] height, int left, int right) {
        int temp;
        for (int i =right-1; i >left ; i--) {
            temp=height[right]-height[i];
            res+=temp;
            height[i]+=temp;
        }
    }

    private void updataLeft(int[] height, int left, int right) {
        int temp;
        for (int i =left+1; i <right ; i++) {
            temp=height[left]-height[i];
            res+=temp;
            height[i]+=temp;
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值