• [python 刷题] 42 Trapping Rain Water


    [python 刷题] 42 Trapping Rain Water

    题目:

    Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

    这题的前置我觉得至少还是得做过 11 Container With Most Water 才好理解一些,毕竟两题的核心思路很像,都是获取容器中所能盛放的最大面积。

    依旧以官方的例子来解释:height = [0,1,0,2,1,0,1,3,2,1,2,1]

    在这里插入图片描述

    这里需要找到的就是两条立柱之间的凹陷的面积,即 m i n ( l , r ) − h [ i ] min(l, r) - h[i] min(l,r)h[i] l l l r r r 可以视作 h [ i ] h[i] h[i] 可能存在的最大立柱。对于 h [ i ] h[i] h[i] 而言,它的面积为:对它而言最高的立柱,再减去其本身的面积。

    其答案就为半透明方块的和:

    在这里插入图片描述

    最简单的一个思路是通过额外存储两个数组进行计算:

    height010210132121
    left011222233333
    right333333332221
    min(l, r)011222232221

    解法如下:

    class Solution:
        def trap(self, height: List[int]) -> int:
            if not height:
                return 0
    
            n = len(height)
            l_max = [0] * n
            r_max = [0] * n
    
            l_max[0] = height[0]
            for i in range(1, n):
                l_max[i] = max(l_max[i - 1], height[i])
    
            r_max[n - 1] = height[n - 1]
            for i in range(n - 2, -1, -1):
                r_max[i] = max(r_max[i + 1], height[i])
    
            return sum(min(l_max[i], r_max[i]) - height[i] for i in range(n))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里 min() 这块求的就是 min(l_max[i], r_max[i]),然后再求 min(l, r) - height[i] 的和

    min(l_max[i], r_max[i]) - height[i] for i in range(n) 是一个 generator expression,会生成一个 generator object,也就是一个 iterable

    sum() 会执行这个 iterable,并且返回相应的总和

    这个解法的时间复杂度和空间复杂度都为 O ( n ) O(n) O(n)

    一个可以做的油画是使用双指针保存 l l l r r r 的下标,并且移动小的那个,如上篇笔记的图示:

    在这里插入图片描述

    在这里插入图片描述

    我稍微去掉了几个半透明的方块,这样看起来稍微清楚一点,本质上来说它的面积还是受限于较短的哪根立柱,因此可以沿用 11 Container With Most Water 的实现,代码如下:

    class Solution:
        def trap(self, height: List[int]) -> int:
            if not height:
                return 0
    
            l, r = 0, len(height) - 1
            l_max, r_max = height[l], height[r]
            res = 0
    
            while l < r:
                print(l_max, r_max)
                if l_max < r_max:
                    l += 1
                    l_max = max(l_max, height[l])
                    res += l_max - height[l]
                else:
                    r -= 1
                    r_max = max(r_max, height[r])
                    res += r_max - height[r]
    
            return res
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这个解法时间复杂度还是 O ( n ) O(n) O(n),不过只遍历了一次,相对还是会比遍历三次快。空间复杂度则是从 O ( n ) O(n) O(n) 优化到了 O ( 1 ) O(1) O(1)

  • 相关阅读:
    零代码编程:用ChatGPT下载lexfridman的所有播客音频和文本
    pycharm中出现这个的原因是什么,如何解决?
    个人电脑(windows、mac)安装Docker Desktop
    用CSS+SVG做一个优雅的环形进度条
    VS2015+Qt5.13.1安装教程
    基于Apache Doris数仓平台架构设计
    阅读书籍:Monte Carlo Methods(第一章 Introduction to Monte CarloMethods)
    VScode mac 一次编辑多行
    经济型EtherCAT运动控制器(七):运动缓冲
    嵌入式Linux裸机开发(一)基础介绍及汇编LED驱动
  • 原文地址:https://blog.csdn.net/weixin_42938619/article/details/133191689