42.接雨水

在这里插入图片描述
参考链接:详细通俗的思路分析,多解法

求每一列的水,我们只需要关注当前列,以及左边最高的墙,右边最高的墙就够了。
装水的多少,当然根据木桶效应,我们只需要看左边最高的墙和右边最高的墙中较矮的一个就够了。

解题思路:

  • ① 最开始我也想是按行计数->超时;
  • ② 按列计数->要找到左右两边最高的柱子,根据(短板高度-当前高度)计算当前列可接的几个单位雨水;
    • 2.1 暴力求左右两边最高的柱子,对所有列都左右遍历一遍,复杂度n*n
    • 2.2 动态规划,用两个数组maxleft[], maxright[]来记录当前下标的左右最高的柱子,遍历一遍maxleft[i] = max(maxleft[i-1], height[i-1]),同理得右边,复杂度2*n,然后遍历一遍求总的雨水单位min(maxleft[i],maxright[i]) - height[i]
    • 2.3 双指针,只需遍历一遍,left=1,right=len()-2(因为最外头的柱子一定没有接到水),
      • if height[left-1] < height[right+1](计算索引为left这一列的水),就说明左边最高的柱子比右边最高的柱子矮(听我解释,
        • 1.如果右边有比左边这个最高的还矮的柱子,但因为有这个右边高柱子在,按照短板原则,取两边最高里矮的,蓄水还得看左边那个;
        • 2.如果右边有比左边这个最高的还高的柱子,那就更加看左边的柱子了(两高取短板))
      • else(计算索引为right这一列的水)
class Solution:
    def trap(self, height: List[int]) -> int:
        # ① 最开始我也想是按行计数->超时;② 按列计数->要找到左右两边最高的柱子,根据(短板高度-当前高度)计算当前列可接的几个单位雨水; 
        # 2.1 暴力求左右两边最高的柱子,对所有列都左右遍历一遍,复杂度n*n
        # 2.2 动态规划,用两个数组maxleft[], maxright[]来记录当前下标的左右最高的柱子,遍历一遍maxleft[i] = max(maxleft[i-1], height[i-1]),同理得右边,复杂度2*n,然后遍历一遍求总的雨水单位min(maxleft[i],maxright[i]) - height[i]
        # 2.3 双指针,只需遍历一遍,left=1,right=len()-2(因为最外头的柱子一定没有接到水),
        # if height[left-1] < height[right+1](计算索引为left这一列的水),就说明左边最高的柱子比右边最高的柱子矮(听我解释,
        #   1.如果右边有比左边这个最高的还矮的柱子,但因为有这个右边高柱子在,按照短板原则,取两边最高里矮的,蓄水还得看左边那个;
        #   2.如果右边有比左边这个最高的还高的柱子,那就更加看左边的柱子了(两高取短板))
        # else(计算索引为right这一列的水)
        left, right = 1, len(height) - 2
        maxleft, maxright = 0, 0
        res = 0
        while left <= right:
            if height[left-1] < height[right+1]:
                maxleft = max(maxleft, height[left-1]) # 短板是左边的最高柱子
                res += max(maxleft - height[left], 0) # 计算蓄水量
                left += 1
            else:
                maxright = max(maxright, height[right+1]) # 短板是右边的最高柱子
                res += max(maxright - height[right], 0) 
                right -= 1
        
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值