【LeetCode刷题笔记(8-1)】【Python】【接雨水】【动态规划】【困难】
文章目录
- 引言
- 接雨水
- 题目描述
- 提示
- 解决方案1:【动态规划】
- 结束语
接雨水
引言
编写通过所有测试案例的代码并不简单,通常需要深思熟虑和理性分析。虽然这些代码能够通过所有的测试案例,但如果不了解代码背后的思考过程,那么这些代码可能并不容易被理解和接受。我编写刷题笔记的初衷,是希望能够与读者们分享一个完整的代码是如何在逐步的理性思考下形成的。我非常欢迎读者的批评和指正,因为我知道我的观点可能并不完全正确,您的反馈将帮助我不断进步。如果我的笔记能给您带来哪怕是一点点的启示,我也会感到非常荣幸。同时,我也希望我的分享能够激发您的灵感和思考,让我们一起在编程的道路上不断前行~
接雨水
题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

图片来源
提示
- n == height.length
- 1 <= n <= 2 * 104
- 0 <= height[i] <= 105
解决方案1:【动态规划】

通过观察图像,我们可以发现红色方框部分与木桶的形态颇为相似。让我们富有想象力地将最左侧高度为2的柱子视作木桶的左侧板,而将最右侧高度为3的柱子视作木桶的右侧板。基于深入人心的【木桶原理】,一个木桶的装水量总是受限于其最短的那块木板。这就意味着,木桶内的水柱高度+柱子高度与左侧板的高度相等时,即达到装水的极限。
更为精妙的是,对于图中的每个位置i,我们都可以将其左侧最高的柱子想象为木桶的左侧板,而将右侧最高的柱子视为木桶的右侧板。这样一来,每个位置的水柱高度+柱子高度height[i]之和,便取决于左侧板和右侧板中较低的那个,恰如木桶原理中所蕴含的深邃智慧。
问题1:对于每个位置i,如何获取其左侧最高柱子的高度left_max[i]和右侧最高柱子的高度right_max[i]呢?
可以通过两次遍历数组height进行获取,代码如下:
# 木桶理论
# 对于位置i,left_max[i]记录的是其左侧最高柱子的高度
left_max = [0] # 对于第0根柱子,其左侧没有柱子,默认其左侧最高柱子的高度为0
# 对于位置n-1-i,right_max[i]记录的是其右侧最高柱子的高度
right_max = [0] # 对于最后一根柱子,其右侧没有柱子,默认其右侧最高柱子的高度为0n = len(height)
# 顺序遍历
for i in range(1, n):# 对于位置i,left_max[-1]记录的是位置i-1其左侧最高柱子的高度---> 只需要和位置i-1的高度height[i-1]进行比较并取最大值即可得到位置i其左侧最高柱子的高度left_max.append(max(left_max[-1], height[i-1]))
# 逆序遍历
for i in range(n-2, -1, -1):# 对于位置i,right_max[-1]记录的是位置i+1其右侧最高柱子的高度---> 只需要和位置i+1的高度height[i+1]进行比较并取最大值即可得到位置i其右侧最高柱子的高度right_max.append(max(right_max[-1], height[i+1]))
# 因为是逆序遍历,需要将结果反转 ---> 反转后, right_max[i]记录的是位置i其右侧最高柱子的高度
right_max = right_max[::-1]# 验证结果
for i in range(n):print("对于第{}根柱子,其高度为{}, 其左侧最高的柱子高度是{},其右侧最高的柱子高度是{}".format(i, height[i], left_max[i], right_max[i]))
运行结果:

观察上图的输入height以及标准输出,可以发现算法成功获取到每个位置i的左侧最高柱子的高度left_max[i]和右侧最高柱子的高度right_max[i],有了这些已知条件后,对于每个位置i,我们可以通过min(left_max[i], right_max[i]) - height[i]得到位置i的水柱高度。
完整代码如下:
class Solution:def trap(self, height: List[int]) -> int:if not height:return 0# 木桶理论# 对于位置i,left_max[i]记录的是其左侧最高柱子的高度left_max = [0] # 对于第0根柱子,其左侧没有柱子,默认其左侧最高柱子的高度为0# 对于位置n-1-i,right_max[i]记录的是其右侧最高柱子的高度right_max = [0] # 对于最后一根柱子,其右侧没有柱子,默认其右侧最高柱子的高度为0n = len(height)# 顺序遍历for i in range(1, n):# 对于位置i,left_max[-1]记录的是位置i-1其左侧最高柱子的高度---> 只需要和位置i-1的高度height[i-1]进行比较并取最大值即可得到位置i其左侧最高柱子的高度left_max.append(max(left_max[-1], height[i-1]))# 逆序遍历for i in range(n-2, -1, -1):# 对于位置i,right_max[-1]记录的是位置i+1其右侧最高柱子的高度---> 只需要和位置i+1的高度height[i+1]进行比较并取最大值即可得到位置i其右侧最高柱子的高度right_max.append(max(right_max[-1], height[i+1]))# 因为是逆序遍历,需要将结果反转 ---> 反转后, right_max[i]记录的是位置i其右侧最高柱子的高度right_max = right_max[::-1]# 获取每个位置i的水柱高度total_rain = 0for i in range(n):water_height = min(left_max[i], right_max[i]) - height[i] # 水柱高度计算公式(根据木桶原理)if water_height > 0: # 水柱高度大于0才有意义total_rain += water_heightreturn total_rain
运行结果:

复杂度分析
- 时间复杂度:O(N),其中 N 是数组
height元素的数量。 - 空间复杂度:O(N)
- 需要存放每个位置左/右侧最高柱子的高度 ===> O(N)
结束语
- 亲爱的读者,感谢您花时间阅读我们的博客。我们非常重视您的反馈和意见,因此在这里鼓励您对我们的博客进行评论。
- 您的建议和看法对我们来说非常重要,这有助于我们更好地了解您的需求,并提供更高质量的内容和服务。
- 无论您是喜欢我们的博客还是对其有任何疑问或建议,我们都非常期待您的留言。让我们一起互动,共同进步!谢谢您的支持和参与!
- 我会坚持不懈地创作,并持续优化博文质量,为您提供更好的阅读体验。
- 谢谢您的阅读!
相关文章:
【LeetCode刷题笔记(8-1)】【Python】【接雨水】【动态规划】【困难】
文章目录 引言接雨水题目描述提示 解决方案1:【动态规划】结束语 接雨水 引言 编写通过所有测试案例的代码并不简单,通常需要深思熟虑和理性分析。虽然这些代码能够通过所有的测试案例,但如果不了解代码背后的思考过程,那么这些代…...
pycharm通过ssh连接远程服务器的docker容器进行运行和调试代码
pycharm连接远程服务器的docker容器通常有两种方法: 第一种:pycharm通过ssh连接已在运行中的docker容器 第二种:pycharm连接docker镜像,pycharm运行代码再自动创建容器 第一种方法比较通用简单,作者比较推崇。 条件…...
Chrome2023新版收藏栏UI改回旧版
版本 120.0.6099.109(正式版本)Chrome浏览器菜单新版、旧版的差异 想要将书签、功能内容改回旧版的朋友可以网址栏输入:「chrome://flags」,接着搜寻「Chrome Refresh 2023」。 最后将 Chrome Refresh 2023、Chrome Refresh 2023…...
WebSocket与JavaScript:实现实时获取位置
一、WebSocket介绍 WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP请求相比,WebSocket能够在服务器和客户端之间建立持久连接,实现实时数据传输。WebSocket提供了较低的延迟和高效的数据传输。在实时舆情监测中,它能够实…...
一种解决Qt5发布release文件引发的无法定位程序输入点错误的方法
目录 本地环境问题描述分析解决方案 本地环境 本文将不会解释如何利用Qt5编译生成release类型的可执行文件以及如何利用windeployqt生成可执行的依赖库,请自行百度。 环境值操作系统Windows 10 专业版(22H2)Qt版本Qt 5.15.2Qt Creator版本5.0…...
UE4/UE5 日志插件(基于spdlog)
1 解决问题 对于高频日志序列化到本地的需求,spdlog肯定完美满足。 源码地址:https://github.com/gabime/spdlog 博主下载的版本为 spdlog-1.12.0,各位大佬可以根绝自己爱好选择。 2 过程介绍 大概目录: SpdlogLibC目录下是对…...
微信小程序ios中非cover组件点击重复触发地图tap事件
现象: map中使用view组件的click事件会重复触发地图的tap组件,只在ios上出现 <map id"maps" style"width: 100vw;height: 100vh;" :latitude"latitude" :longitude"longitude":markers"markers"…...
7.26 SpringBoot项目实战【还书】
文章目录 前言一、编写控制器二、编写服务层三、Git提交前言 本文是项目实战 业务接口 的最后一篇,上文 曾说过【还书】的 入口是【我的借阅记录】,因为【还书】是基于一次借阅记录而言,另外在4.2 数据库设计 曾分析过【还书】的业务场景,需要执行两步操作: 更新【借阅记…...
Golang中使用errors返回调用堆栈信息
Golang的errors包返回堆栈信息 标准库errors提供了处理错误的方法。比如常用的 func New(text string) error 用该方法处理错误信息,就只会输出自定义的 text 到控制台或者日志文件,没有其它辅助排查的信息输出,所以常规我们就只能根据 te…...
Web前端-HTML(常用标签)
文章目录 1. HTML常用标签1.1 排版标签1)标题标签h (熟记)2)段落标签p ( 熟记)3)水平线标签hr(认识)4)换行标签br (熟记)5)div 和 span标签(重点)6)排版标签总结 1.2 标签属性1.3 图像标签img (重点)1.4 链…...
一 OpenCV中的数据类型
1. cv::Mat 2. cv::Point 主要用来表示二维点,也有表示三维点的模板类型; cv::Point p(int, int) 最常用 ① cv::Point_<T> ② cv::Point2i cv::Point_<int> ③ cv::Point2f cv::Point_<float> ④ cv::Point2d …...
59. 螺旋矩阵 II(java实现,史上最详细教程,想学会的进!!!)
今天来分享一下螺旋矩阵的解题思路及代码的实现。 题目描述如下: 首先拿到这道题,首先不要慌张,我们来仔细分析一下会发现并没有那么难。 首先看下边界的元素是1、2、3递增的,那么我们也许可以根据这一点先把边界的元素一个一个给…...
vue 将后端返回的二进制流进行处理并实现下载
什么是二进制流文件? 二进制文件是一种计算机文件格式,它的数据以二进制形式存储,与文本文件不同。二进制文件可以包含任意类型的数据,例如图像、音频、视频、可执行文件、压缩文件等,而文本文件则仅仅包含 ASCII 码或…...
PyCharm连接远程服务器
要求:PyCharm专业版才支持远程服务 一、创建远程连接 先建立本地与远程服务器之间的SSH连接 1、配置连接 2、建立SSH连接,选择文件传输协议 SFTP 3、设置服务器名(可以随意命名) 4、配置 SSH连接 点击 172.18.1.202 配置…...
使用Qt制作网易云播放器的歌曲排行界面
!!!直接上图!!! !!!直接上图!!! !!!直接上图!!! 网易云排行榜…...
【.NET Core】特性(Attribute)详解
【.NET Core】特性(Attribute)详解 文章目录 【.NET Core】特性(Attribute)详解一、概述二、编写自定义属性2.1 自定义特性的主要步骤2.2 应用AttributeUsageAttributeAttributeTargets 成员Inherited属性AllowMultiple属性 三、声…...
【C++】POCO学习总结(十九):哈希、URL、UUID、配置文件、日志配置、动态库加载
【C】郭老二博文之:C目录 1、哈希 1.1 说明 std::map和std::set 的性能是:O(log n) POCO哈希的性能比STL容器更好,大约快两; POCO中对应std::map的是:Poco::HashMap; POCO中对应std::set的是 Poco::Hash…...
1846_安全SPI
Grey 全部学习内容汇总:GitHub - GreyZhang/g_embedded: some embedded basic knowledge. 1846_安全SPI SPI是一种常见的通信方式,在汽车电子中比较常用。但是如果涉及到安全相关的设计,可能得考虑更多。而SPI协议本身没有很好的标准化&am…...
SQL Server ,使用递归查询具有层级关系的数据。
假设我们有一个表格 Employees,其中包含员工的层级关系信息,每一行包括员工的ID、姓名以及上级员工的ID。 下面是一个示例表格及其数据: Employees ---------------------- EmployeeID | Name | ManagerID ---------------------- 1 …...
【参数汇总】mysql服务端/客户端常见优化参数
mysql服务端参数 1、innodb_buffer_pool_size (innodb索引buffer pool缓冲区大小) 默认大小为128M, 官方推荐其配置为系统内存的 50% 到 75% 。 一般innodb_buffer_pool_size要结合以下两个参数来设置: innodb_buffer_pool_ch…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
