0042接雨水

接雨水
在这里插入图片描述
暴力法:

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        len_height = len(height)
        i = 1
        sum = 0

        while i < len_height - 1:
            j = i + 1
            while j < len_height and height[i] == height[j]:  # 找到i右侧第一个不同于i的数
                j += 1
            if j == len_height:  # 当j 到达边缘且任未找到不同于i的元素时 可以认定 i的右侧无法接雨水
                return sum
            if height[i - 1] > height[i] < height[j]:  # 当i为当前局部最小值时,开始计算能存储的雨水的量
                res, right = self.get_sum(height, i)  # 返回计算结果与接到水的右侧坐标
                sum += res
                i = right
            i += 1
        return sum

    def get_sum(self, height, index):
        i = index
        while i > 0:  # 寻找i左侧的局部最大值
            if height[i] > height[i - 1]: 
                break
            i -= 1
        left = i
        i = index
        while i < len(height) - 1:  # 寻找i右侧的局部最大值
            if height[i] > height[i + 1] and (height[left] <= height[i] or height[i] == max(height[index + 1:])):
                # 要使得接水的量最多,应当保证右侧墙满足一下特点
                # 1. 第i号墙需要比i-1号墙高
                # 2. 第i号墙为右侧最高墙或者i号墙比左侧墙高
                break
            i += 1
        right = i
        x = min(height[left], height[right])
        sum = 0
        for i in range(left + 1, right):
            sum += max(x - height[i], 0)
        return sum, right

动态规划

    def trap(self,height):
        len_height = len(height)
        left_max = [0 for _ in range(len_height)]  # left_max[i]表示 i号位置左边最高墙
        right_max = [0 for _ in range(len_height)]  # right_max[i]表示 i号位置右侧最高墙
        left_max[0] = height[0]  # 初始化
        right_max[-1] = height[-1]
        for i in range(1,len_height):
            left_max[i] = max(left_max[i-1],height[i])  # 如果i号位置为最高墙,则赋值 否则则为i-1号的值
        for i in reversed(range(len_height-1)):
            right_max[i] = max(right_max[i+1], height[i])
        ans = sum(min(left_max[i],right_max[i])-height[i] for i in range(len_height))
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值