LeetCode题目42:接雨水【python 42/1000】

news2024/11/25 10:31:27

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

LeetCode题目42 “接雨水”要求计算在给定的非负整数数组中,数组中的数字表示高度图,计算下雨后能接多少雨水。本文将详细介绍三种解决这一问题的方法,包括解题思路、详细的代码实现以及算法分析。

题目描述

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

输出:在此高度图中能接的雨水总量。

示例
在这里插入图片描述

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

方法一:暴力法

解题步骤

  1. 对每个元素:计算左边和右边最高的墙的高度。
  2. 计算接水量:对于每个元素,找到其左右两边最高的墙的较小者,这个值减去当前高度就是该位置能接的水量。
  3. 求和:将所有位置的接水量累加起来。

代码示例

def trap(height):
    """
    使用暴力解法计算接雨水问题
    :param height: List[int],表示柱子的高度
    :return: int,接到的雨水总量
    """
    if not height:
        return 0

    n = len(height)  # 柱子的总数
    total_water = 0  # 初始化总雨水量为0

    # 遍历每个柱子,除了最左边和最右边的柱子,因为它们不能接雨水
    for i in range(1, n - 1):  
        left_max = 0  # 初始化左边最高柱子高度为0
        right_max = 0  # 初始化右边最高柱子高度为0
        
        # 查找左边最高的柱子
        for j in range(i):
            left_max = max(left_max, height[j])
        
        # 查找右边最高的柱子
        for j in range(i + 1, n):
            right_max = max(right_max, height[j])
        
        # 计算当前位置最多可以接的雨水量,取决于左右两边较矮的柱子
        water = min(left_max, right_max) - height[i]
        
        # 如果计算出的水量大于0,则累加到总雨水量中
        if water > 0:
            total_water += water

    return total_water

# 示例调用
print(trap([0,1,0,2,1,0,1,3,2,1,2,1]))  # 输出: 6

算法分析

  • 时间复杂度:O(N^2),其中 N 是数组长度。对每个元素进行左右最大值搜索。
  • 空间复杂度:O(1)。

方法二:动态规划

解题步骤

  1. 预处理:创建两个数组 left_maxright_maxleft_max[i] 存储从左到 i 的最大高度,right_max[i] 存储从右到 i 的最大高度。
  2. 计算接水量:遍历每个位置,使用预处理的数组计算该位置能接的水量。
  3. 求和:累加每个位置的接水量。

代码示例

def trap(height):
    """
    使用动态规划解法计算接雨水问题
    :param height: List[int],表示柱子的高度
    :return: int,接到的雨水总量
    """
    if not height:
        return 0

    n = len(height)
    total_water = 0  # 总雨水量
    left_max = [0] * n  # 左侧最大高度数组
    right_max = [0] * n  # 右侧最大高度数组

    # 填充左侧最大高度数组
    left_max[0] = height[0]
    for i in range(1, n):
        left_max[i] = max(left_max[i - 1], height[i])

    # 填充右侧最大高度数组
    right_max[n - 1] = height[n - 1]
    for i in range(n - 2, -1, -1):
        right_max[i] = max(right_max[i + 1], height[i])

    # 计算积水量
    for i in range(1, n - 1):
        water = min(left_max[i], right_max[i]) - height[i]
        total_water += water

    return total_water

# 示例调用
print(trap([0,1,0,2,1,0,1,3,2,1,2,1]))  # 输出: 6

算法分析

  • 时间复杂度:O(N),进行了三次线性扫描。
  • 空间复杂度:O(N),使用了两个额外的数组来存储左右最大值。

方法三:双指针

解题步骤

  1. 初始化指针:使用两个指针 leftright,分别指向数组的开头和结尾。
  2. 移动指针:根据 left_maxright_max 的关系决定是移动 left 还是 right 指针。
  3. 计算接水量:根据当前的 left_maxright_max,计算当前指针位置能接的水量,并更新总量。
  4. 终止条件:当 left 大于或等于 right 时停止。

代码示例

def trap(height):
    """
    使用双指针解法计算接雨水问题
    :param height: List[int],表示柱子的高度
    :return: int,接到的雨水总量
    """
    if not height:
        return 0

    left, right = 0, len(height) - 1  # 初始化左右指针
    left_max, right_max = 0, 0        # 初始化左右最大高度
    total_water = 0                   # 初始化总雨水量

    while left < right:
        if height[left] < height[right]:
            if height[left] >= left_max:
                left_max = height[left]  # 更新左侧最大高度
            else:
                total_water += left_max - height[left]  # 计算左侧的积水
            left += 1  # 移动左指针
        else:
            if height[right] >= right_max:
                right_max = height[right]  # 更新右侧最大高度
            else:
                total_water += right_max - height[right]  # 计算右侧的积水
            right -= 1  # 移动右指针

    return total_water

# 示例调用
print(trap([0,1,0,2,1,0,1,3,2,1,2,1]))  # 输出: 6

算法分析

  • 时间复杂度:O(N),只需遍历数组一次。
  • 空间复杂度:O(1),使用了常数空间。

总结

在这里插入图片描述
这三种方法从暴力法到优化的双指针法逐步提高了效率和降低了复杂度。在实际应用中,选择哪种方法取决于对时间和空间效率的具体需求。如果需要快速解决问题并且可以使用一些额外空间,动态规划是一个不错的选择;如果对空间有严格限制,双指针法提供了最优的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1607262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[C++][算法基础]求约数(试除法)

给定 n 个正整数 &#xff0c;对于每个整数 &#xff0c;请你按照从小到大的顺序输出它的所有约数。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含一个整数 。 输出格式 输出共 n 行&#xff0c;其中第 i 行输出第 i 个整数 的所有约数。 数据范围 1≤…

直播预告:拥抱AI-探索AI大模型在邮件反钓鱼检测的应用

随着ChatGPT的问世&#xff0c;生成式AI技术迅速渗透到我们生活的各个角落&#xff0c;以ChatGPT为代表的生成式AI技术&#xff0c;依托其强大的AI模型和海量数据&#xff0c;赢得了广泛的欢迎。 然而&#xff0c;生成式AI的不断演进也带来了新的挑战。大型语言模型&#xff08…

单链表-通讯录

目录 单链表实现 通讯录代码实现 初始化 初始化函数 添加 删除 展示 查找 修改 销毁 代码展示 main.c text.c text.h list.c list.h 和前面的通讯录实现差不多这次就是实现一个以单链表为底层的通讯录 单链表实现 数据结构&#xff1a;单链表-CSDN博客 通讯…

【资源分享】SPSS 26免费下载安装

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

(51单片机)第十一章-串行口应用提高

11.1 方式0应用 在第6章中&#xff0c;已经对51单片机的串行口结构做过详细介绍&#xff0c;并且通过实例讲解了串行口的4种工作方式中方式1的具体用法&#xff0c;本节详细讲述串行口方式0的用法。 串行口方式0被称为同步移位寄存器的输入/输出方式&#xff0c;主要用于扩展并…

量化系统QTYX使用攻略|“选股框架”篇——组合对比分析,孰优孰劣一目了然(更新2.8.2)...

2024龙年大吉&#xff01;整装待发&#xff01;知识星球《玩转股票量化交易》精华内容概览 搭建自己的量化系统 股票量化交易系统QTYX是一个即可以用于学习&#xff0c;也可以用于实战炒股分析的系统。 分享QTYX系统目的是提供给大家一个搭建量化系统的模版&#xff0c;最终帮助…

OCP Java17 SE Developers 复习题13

答案 D, F. There is no such class within the Java API called ParallelStream, so options A and E are incorrect. The method defined in the Stream class to create a parallel stream from an existing stream is parallel(); therefore, option F is correct, and o…

【粉丝福利 | 第5期】教你快速入门三大层次学习企业架构框架TOGAF

⛳️ 写在前面参与规则&#xff01;&#xff01;&#xff01; ✅参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff0c;任意评论&#xff08;每人最多评论三次&#xff09; ⛳️本次送书1~4本【取决于阅读量&#xff0c;阅读量越多&#xff0c;送的越多】 三大层次学习…

想冲银行去了!

这次给大家分享银行的Java后端面经&#xff0c;面试难度相比互联网大厂小了很多&#xff0c;面试时间大概是 10-30 分钟&#xff0c;技术面试的时间直接缩减一半&#xff01;而且&#xff0c;问的问题也相对比较简单一些。 今天主要分享杭州银行、招商银行网络科技的技术面试问…

相机摄影入门技巧,数码摄影技巧大全

一、资料前言 本套数码相机摄影资料&#xff0c;大小1.08G&#xff0c;共有42个文件。 二、资料目录 《aking人像摄影技巧分享》.pdf 《Nikon.D90数码单反摄影技巧大全》FUN视觉.全彩版.pdf 《不可不学的摄影技巧》.pdf 《常用场景摄影》.pdf 《单反数码摄影专家技法》.…

java学习笔记6

11. 类的封装 ​ 在Java中,**封装(Encapsulation)**是面向对象编程中的重要概念,它指的是将类的数据(属性)和行为(方法)绑定在一起,并对外部隐藏数据的具体实现细节,只通过公共方法来访问和操作数据。这有助于提高代码的安全性、可维护性和灵活性。 11.1 为什要封装 …

electron打包编译国产统信uos系统 arm架构 x86架构 linux mac等环境

electron v21版本以上统信UOS会提示gbm_bo_map错误&#xff0c;可使用v8~v21版本的electron 打包linux包需要再linux系统下运行编译&#xff0c;arch可以指定架构 如果要在统信uos上运行&#xff0c;需要打包成deb格式&#xff0c;在target中修改成deb 或者用第三方软件把app…

3. 无重复字符的最长子串/438. 找到字符串中所有字母异位词/560. 和为 K 的子数组

3. 无重复字符的最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 思路&#xff1a;想象一下我们…

C语言 选择控制结构(1) 了解选择结构 关系运算符讲解 基本逻辑判断演示

接下来 我们来说 选择控制结构 在生活中 我们也有很多需要分支结构的例子 比如: 计算两个整数的最大值 计算n个数的最大值&#xff0c;最小值 判断三角形三边能否构成三角形? 判断某年是否是闰年? 判断输入的英文字母是大写还是小写? 我们在程序开发中 需要根据某种条件 进…

重磅!Meta 发布 Llama 3,前所未有的强大功能和多模态能力|TodayAI

Meta今日宣布推出其最新一代尖端开源大型语言模型Llama 3。该模型预计很快将在多个领先的云服务平台上线&#xff0c;包括AWS、Databricks、Google Cloud、Hugging Face、Kaggle、IBM WatsonX、Microsoft Azure、NVIDIA NIM和Snowflake。 Llama 3模型得到了AMD、AWS、Dell、In…

解决VirtualBox虚拟机启动失败的问题

一.出现的问题&#xff08;未能启动虚拟电脑&#xff0c;由于物理网卡未找到&#xff09; 一、错误信息分析 “未能启动虚拟电脑&#xff0c;由于物理网卡未找到”&#xff1a;这个错误通常是由于VirtualBox无法识别或连接到物理网卡造成的。可能是由于驱动程序问题、网络设置错…

Hadoop——Yarn 调度器和调度算法

Yarn 调度器和调度算法 YARN调度器&#xff08;Scheduler&#xff09;是负责将集群资源分配给不同应用程序的组件。它根据应用程序的资源需求和优先级&#xff0c;以及集群的资源供给情况&#xff0c;决定如何分配资源。YARN提供了多种调度器实现&#xff0c;每种调度器都有不…

力扣:219. 存在重复元素 II

力扣&#xff1a;219. 存在重复元素 II 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

服务调用-微服务小白入门(4)

背景 各个服务应用&#xff0c;有很多restful api&#xff0c;不论是用哪种方式发布&#xff0c;部署&#xff0c;注册&#xff0c;发现&#xff0c;有很多场景需要各个微服务之间进行服务的调用&#xff0c;大多时候返回的json格式响应数据多&#xff0c;如果是前端直接调用倒…

ST-GCN模型详解(+openpose)

ST-GCN模型详解&#xff08;openpose&#xff09; 一、什么是ST-GCN呢 基于骨架的动作识别&#xff08;Skeleton-Based Action Recognition&#xff09;主要任务是从一系列时间连续的骨骼关键点&#xff08;2D/3D&#xff09;中识别出正在执行的动作。因为牵涉到骨骼框架这种…