【LeetCode刷题笔记(8-3)】【Python】【接雨水】【双指针】【困难】

文章目录

  • 引言
  • 接雨水
    • 题目描述
    • 提示
  • 解决方案3:【双指针】
  • 结束语

接雨水

【LeetCode刷题笔记(8-1)】【Python】【接雨水】【动态规划】【困难】

【LeetCode刷题笔记(8-2)】【Python】【接雨水】【单调栈】【困难】

引言

编写通过所有测试案例的代码并不简单,通常需要深思熟虑理性分析。虽然这些代码能够通过所有的测试案例,但如果不了解代码背后的思考过程,那么这些代码可能并不容易被理解和接受。我编写刷题笔记的初衷,是希望能够与读者们分享一个完整的代码是如何在逐步的理性思考下形成的。我非常欢迎读者的批评和指正,因为我知道我的观点可能并不完全正确,您的反馈将帮助我不断进步。如果我的笔记能给您带来哪怕是一点点的启示,我也会感到非常荣幸。同时,我也希望我的分享能够激发您的灵感和思考,让我们一起在编程的道路上不断前行~

接雨水

题目描述

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

在这里插入图片描述
图片来源

提示

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

解决方案3:【双指针】

在【LeetCode刷题笔记(8-1)】【Python】【接雨水】【动态规划】【困难】和【LeetCode刷题笔记(8-2)】【Python】【接雨水】【单调栈】【困难】中,我们详细阐述了如何在一步步理性分析下基于【动态规划】和【单调栈】设计完整的算法和代码通过接雨水的所有测试用例。这两种算法的空间复杂度都是O(n),其中动态规划法需要额外维护两个长度为N的数组left_max_listright_max_list,用于记录每个位置i ,其左侧柱子的最大高度left_max_list[i]和右侧柱子的最大高度right_max_list[i]

具体来说,我们首先从左到右完整地遍历数组height得到left_max_list,然后再从右往左完整地遍历数组height得到right_max_list。实际上,这相当于把【接雨水】问题的解决策略分成两个相对独立的步骤:

  1. 获取每个位置i ,其左侧和右侧柱子的最大高度。这一步需要两个for循环,分别从左到右和从右到左遍历数组。

  2. 根据木桶原理,以及步骤1获取的必要信息,得到最终的雨水总量。这一步还需要一个for循环,遍历整个数组。

问题1:有没有其它策略能够把步骤一和步骤二结合起来,即在一个循环下解决【接雨水】问题?

有,双指针。

在上面的分析过程中,我们发现步骤1的两个循环,一个是从左往右,一个是从右往左,这种遍历方法和双指针非常类似。因此,我们考虑是否可以用左指针替代从左往右的循环,同时用右指针替代从右往左的循环。这样,我们可以在一次遍历中完成两个步骤,提高算法的效率。

不仅可以,而且还买一送一,顺带解决了获取位置i雨水量的问题。

1. 当左指针left从左往右的移动过程中,我们可以通过left_max记录区间[0,left]的最大高度 。同理,当右指针right从右往左的移动过程中,我们也可以通过right_max记录区间[right,n-1]的最大高度。

关键问题2:如何决定下一步是移动左指针还是右指针?

当能确定位置left的接水量时,left右移;当能确定位置right的接水量时,right左移;

对于当前左指针的位置left,[0, left]区间的最大高度left_max是已知的,并且[right,n-1]区间的最大高度right_max也是已知的。根据木板原理,一个木桶的装水量总是受限于其最短的那块木板 ⇒ 此时left_max<right_max成立 ⇒ [0, left]的最高左木板 < [right, n-1]区间的最高右木板 <= [left+1, n-1]区间的最高右木板 恒成立⇒ 位置left的装水量由[0, left]的最高左木板决定,而[0, left]的最高左木板已经是板上钉钉 ⇒ 自然可以计算位置left的接水量water_left = left_max - height[left];既然位置left的接水量已经确定,下一步自然是left右移。

同理,对于当前右指针的位置right,[0, left]区间的最大高度left_max是已知的,并且[right,n-1]区间的最大高度right_max也是已知的 ⇒ 此时right_max < left_max成立 ⇒ [right, n-1]区间的最高右木板 < [0, left]的最高左木板 <= [0,right-1]区间的最高左木板 恒成立⇒ 位置right的装水量由 [right, n-1]区间的最高右木板决定,而 [right, n-1]区间的最高右木板的值已经是板上钉钉 ⇒ 自然可以计算位置right的接水量water_right = right_max - height[right];既然位置right的接水量已经确定,下一步自然是right左移。

完整代码如下

class Solution:  def trap(self, height: List[int]) -> int:  # 初始化结果为0  total_water = 0  # left指向数组的起始位置  left = 0  # right指向数组的末尾位置  right = len(height) - 1  # left_max记录从左到left的最大高度  left_max = 0  # right_max记录从right到数组末尾的最大高度  right_max = 0  # 当left小于right时,持续进行以下操作  while left < right:  # 更新left_max为当前left位置的高度和left_max中的较大值  left_max = max(left_max, height[left])  # 更新right_max为当前right位置的高度和right_max中的较大值  right_max = max(right_max, height[right])  if left_max < right_max:  # left_max小于right_max ==> 依据木桶原理 ==> 位置left雨水量由左木板最大高度和位置left的柱子高度共同确定  total_water += left_max - height[left]  # 向右移动left  left += 1  else:  # right_max大于等于left_max ==> 依据木桶原理 ==> 位置right的雨水量由左木板最大高度和位置left的柱子高度共同确定  total_water += right_max - height[right]  # 向左移动right  right -= 1  # 返回最终的雨水量  return total_water

运行结果
在这里插入图片描述

复杂度分析

  • 时间复杂度:O(N),其中 N 是数组height元素的数量。
  • 空间复杂度:O(1)
    • 利用双指针动态记录区间[0, left] 和[right, N-1]的最大值 ===> O(1)

结束语

  • 亲爱的读者,感谢您花时间阅读我们的博客。我们非常重视您的反馈和意见,因此在这里鼓励您对我们的博客进行评论。
  • 您的建议和看法对我们来说非常重要,这有助于我们更好地了解您的需求,并提供更高质量的内容和服务。
  • 无论您是喜欢我们的博客还是对其有任何疑问或建议,我们都非常期待您的留言。让我们一起互动,共同进步!谢谢您的支持和参与!
  • 我会坚持不懈地创作,并持续优化博文质量,为您提供更好的阅读体验。
  • 谢谢您的阅读!

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

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

相关文章

Arcgis新建矢量并手动绘制范围

新建一个shapefile&#xff0c;并选择面 得到了一个新shape 然后右击&#xff0c;开始编辑&#xff0c;打开编辑器

mysql 当前时间加3个工作日

1. 问题描述&#xff1a; 在日常工作中可能会遇到计算工作日的情况 2. 解决过程 (1) 首先制作一个假日表 holiday_config CREATE TABLE holiday_config (id int(10) NOT NULL AUTO_INCREMENT,holiday varchar(8) DEFAULT NULL,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB…

issue queue的实现方式

主要从一下几个点进行考虑&#xff1a; 集中式&#xff08;Centrallized&#xff09;或者分布式(Distributed)&#xff1b;压缩式&#xff08;Compressing&#xff09;或者非压缩式(Non-compressing)&#xff1b;数据捕捉的方式&#xff08;Data-capture&#xff09;或者非数据…

matlab中Signal Builder模块的用法总结

目录 前言方法一方法二参考文章 前言 今天在用matlab中Signal Builder的模块时&#xff0c;不知道怎么去得到想要的信号源&#xff0c;于是上网查了一下&#xff0c;并记录一下 方法一 如图所示&#xff0c;打开自定义 上面一行是横坐标&#xff0c;下面一行是纵坐标 [0,1…

什么是Symbol?在实际开发中怎么用?

Symbol 是 ECMAScript 6&#xff08;ES6&#xff09;引入的一种新的基本数据类型。Symbol 类型的值是唯一且不可变的。目的是确保对象属性使用唯一标识符&#xff0c;不会发生属性冲突的危险。 1. 使用Symbol() 创建 调用 Symbol()函数时&#xff0c;也可以传入一个字符串参数…

ubuntu docker镜像制作及常用命令

ubuntu docker镜像制作及常用命令 一、安装docker 1、安装 sudo apt install docker.io 2、拉取ubuntu镜像 sudo docker pull ubuntu:18.04 3、从Dockerfile构建镜像 3.1、 Dockerfile示例 FROM ubuntu:18.04MAINTAINER [user] [email]RUN apt-get update \&& …

.NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证

public Task InvokeAsync(HttpContext context){// 获取终点路由特性var endpointFeature context.Features.Get<IEndpointFeature>();// 获取是否定义了特性var attribute endpointFeature?.Endpoint?.Metadata?.GetMetadata<AllowAnonymousAttribute>();if …

CentOS 7部署vsftpd

&#xff08;1&#xff09;概述 vsftpd是Linux上一个非常流行的FTP服务器软件。它使用简单&#xff0c;功能强大&#xff0c;安全性高。本文将介绍如何在CentOS 7上部署vsftpd服务器。 &#xff08;2&#xff09;安装vsftpd 使用yum命令安装vsftpd&#xff1a; yum install…

二叉树题目:二叉树着色游戏

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树着色游戏 出处&#xff1a;1145. 二叉树着色游戏 难度 6 级 题目描述 要求 两位玩家参与二叉树着色游戏。给定二叉树的根结点 root \textt…

【稳定检索|投稿优惠】2024年公共服务、健康与医药国际会议(ICPSHM 2024)

2024年公共服务、健康与医药国际会议(ICPSHM 2024) 2024 International Conference on Public Services, Health, and Medicine(ICPSHM) 一、【会议简介】 ​2024年公共服务、健康与医药国际会议&#xff08;ICPSHM 2024&#xff09;将于三亚这片美丽的海滨城市盛大召开。我们诚…

送货服务Grupo RÃO将在Moonbeam上通过DUX推出Web3支持的忠诚度计划

波卡上的首选多链开发平台Moonbeam宣布使用由Account Abstraction提供支持的DUX智能钱包为Grupo RO推出Web3忠诚度计划。此次合作为Grupo RO食品配送服务带来了新的奖励计划&#xff0c;其中包括折扣、产品、优惠券、竞赛等福利的订阅 — 所有这些都得益于Moonbeam的区块链技术…

UDP特性之组播(多播)

UDP特性之组播 1. 组播的特点2. 设置主播属性2.1 发送端2.2 接收端 3. 组播通信流程3.1 发送端3.2 接收端 4. 通信代码 原文链接 在公司测试广播和多播有一点问题。。。 1. 组播的特点 组播也可以称之为多播这也是UDP的特性之一。组播是主机间一对多的通讯模式&#xff0c;是…

URP管线下Shader中的SubShader Tags、Pass Tags、ShaderLab Commands总结

一、SubShader Tags SubShader Tags是提供SubShader信息的键值对&#xff0c;它们允许你指定特定的设置好让渲染管线知道如何处理SubShader。 下面分别介绍一下SubShader中的tag。 1、 RenderPipeline 这个tag用来指定SubShader的目标渲染管线&#xff0c;不同的渲染管线有特定…

Vue3源码梳理:运行时之基于h函数生成vnode的内部流程

VNode 节点类型 对于vnode而言&#xff0c;具备很多节点类型vue源码中patch函数switch处理包含了好几种类型&#xff0c;常见类型如下 Text&#xff1a;文本节点Comment&#xff1a;注释节点Static&#xff1a;静态dom节点Fragment&#xff1a;包含多个根节点的模板被表示为一…

SHT10温湿度传感器——STM32驱动

———————实验效果——————— &#x1f384;硬件外观 &#x1f384;接线 &#x1f388; 3.3V供电 &#x1f388; IIC通讯 &#x1f384; 代码获取 &#x1f388; 查看下方 ———————END———————

FB使用汇编模拟GoSub(子函数)功能

在FB里不支持GoSub功能&#xff0c;在面对函数内简单又重复的操作&#xff0c;而所涉及变量又比较多的时候&#xff0c;再在外边定义一个函数就显得累赘&#xff0c;此时如果可以有一个函数内部的子函数&#xff0c;就显得方便多了。 在汇编探索里发现&#xff0c;可以使用汇编…

20231218在微软官网下载WINDOWS10以及通过rufus-4.3p写入U盘作为安装盘

20231218在微软官网下载WINDOWS10以及通过rufus-4.3p写入U盘作为安装盘 2023/12/18 17:06 百度搜索&#xff1a;下载 windows10 https://www.microsoft.com/zh-cn/software-download/windows10 下载 Windows 10 更新之前&#xff0c;请参阅 Windows 版本信息状态中的已知问题&a…

企业要想成功就必须培养“支持说真话的文化”

大家好&#xff0c;欢迎来到我的博客。今天&#xff0c;我想和大家谈谈企业文化的重要性&#xff0c;特别是支持说真话的文化。 1. 为什么说真话很重要&#xff1f; 在当今社会&#xff0c;说真话似乎越来越难了。我们害怕得罪别人&#xff0c;害怕被孤立&#xff0c;害怕被认…

系统设计——系统安全

HTTPS 是如何工作的&#xff1f; 安全超文本传输​​协议&#xff08;HTTPS&#xff09;是超文本传输​​协议&#xff08;HTTP&#xff09;的扩展。HTTPS 使用传输层安全性&#xff08;TLS&#xff09;传输加密数据。如果数据在网上被劫持&#xff0c;劫持者得到的只是二进制…

php去掉数组的key,重组数组的方法

php去掉数组的key&#xff0c;重组数组的方法 方法一&#xff1a;foreach循环方法二&#xff1a;array_values()函数方法三&#xff1a;array_map()函数方法四&#xff1a;强制类型转换 方法一&#xff1a;foreach循环 使用foreach循环遍历数组时&#xff0c;可以只取出数组的…