LeetCode:接雨水上台阶解法

2 篇文章 0 订阅

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

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

刚看到这道题的时候,基本没什么思路。但盯着图看了会,突然想到是否可以以上台阶的思路去解决。
所谓上台阶是指我们从一侧开始遍历,当遇到比自己目前所站柱子更高的柱子的时候,就登上去;当遇到跟自己目前所站柱子一样高的柱子时我们就直接走上去;当遇到比自己目前所站的柱子低的柱子时,为了防止我们摔伤,我们需要填充柱子或者叫雨水。登上最高的柱子后,一侧的遍历结束。转头从另一侧开始执行上台阶的步骤。最终我们填充的柱子或雨水数就是答案。代码如下

class Solution {
    public int trap(int[] height) {
        if(height.length==0) {
            return 0;
        }
        int step = 0;
        int rains = 0;
        int maxHeightI = 0;
        int maxHeight = height[0];
        for(int i=1;i<=height.length-1;i++) {
            if(height[i] >= maxHeight) {
                maxHeight = height[i];
                maxHeightI = i;
            }
        }
        for(int i=0;i<=maxHeightI;i++) {
            if(height[i] > step) {
                step = height[i];
            } else if(height[i] < step){
                rains += step - height[i];
            }
        }
        step = 0;
        for(int i=height.length-1;i>maxHeightI;i--) {
            if(height[i] > step) {
                step = height[i];
            } else if(height[i] < step){
                rains += step - height[i];
            }
        }
        return rains;
    }
}

我们用step来表示我们目前所站的高度,初始为0。rains表示最终结果,初始为0。我们首先需要用一次遍历去查找最高的柱子所在的下标。可能有多个最高值,我们取最后一个。
然后我们从左侧开始遍历,如果柱子的高度大于我们目前所站的高度,就把柱子的高度赋值给step,相当于我们爬上了新的柱子;如果柱子高度小于我们目前所站的高度,为了防止我们摔伤,我们要填充柱子高度与我们目前所站高度的差值。填充的值累加到rains。当我们碰到最高值,循环结束。
将step清零,从右侧开始遍历,逻辑是一样的。
最终返回rains就是结果。
看了官网的几种解法,感觉不太好理解。基于上台阶的思路比较容易理解。时间复杂度是O(n),我们需要两遍遍历;空间复杂度方面使用了step和maxHeightI变量,复杂度是O(1)。时间复杂度和空间复杂度也能够接受

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值