当前位置: 首页 > news >正文

LeetCode42(接雨水)[三种解法:理解动态规划,双指针,单调栈]

接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述
在这里插入图片描述
这是一道困难题,难度确实有点层次.我们先来朴素思想走一波.
要求能接多少雨水,我们可以具化到每个硅谷,每个硅谷能存多少雨水,那么答案就是每个硅谷的雨水所加之和.
对于每一个高度的柱子,我们要求出它的积水量,是等于它左边高度的最大值与右边高度的最大值中这两个值其中的小值减去当前硅谷的高度.
公式为:
在这里插入图片描述在这里插入图片描述

怎么理解这句话呢?为什么不是这个硅谷两旁的高度相比较较小值减去当前硅谷的高度,而是其左右两边的最大值呢.

对于这一小块,我们观察到积水处的左右两边好像跟我们拿其左右两边最大值与它身边两个的最小值所取到的积水处的值是一样的.
在这里插入图片描述

我们仔细来看看中间那部分.
在这里插入图片描述
这一部分如果取两边的值,我们将会漏掉上方那一个单位的正方形值,所以对于积水处的两旁界限我们应该是选取左右两边的最大值.

而为什么又要减去积水处的高度呢?我们再来看下面这一部分
在这里插入图片描述
其实不用我解释,现在看这幅图大家都能理解啦,我们肯定是需要减去它的基础高度值,才能求得实际上空的空间.也就是硅谷的面积.

所以基于这种求值的思路,我们开始来正式解题.

暴力法解题

我们谈到是要取一个硅谷点的左右两边最大值来求值.那么每当我们到达一个结点处,遍历它的左右两边找到其左右的最大值就可以完成这一步骤的计算.但由于每一个结点我们都需要遍历一遍数组,所以时间复杂度为O(²)
我相信大家应该都可以基于暴力能自主完成,这里不做代码解释,下面才是算法重点.

动态规划

我们谈到一个节点的左右两边的最大值.我们可不可以在计算之前,统计好每一个结点的左右两边的最大值.
也就是从左往右开始遍历,我们可以求得每个结点右边的最大值.
rightMax[i]=max(rightMax[i+1],height[i])
同理,从右往左遍历,我们可以求得每个结点左边的最大值.
leftMax[i]=max(leftMax[i−1],height[i])
总之就是在遍历计算前,我们打表把所有每个结点的左右两边的最大值存储好,之后我们要求时直接从打表过后的数组里面取就可
代码为

public int dpMethod(int[] height){int[] leftdp = new int[height.length];int[] rightdp = new int[height.length];int leftMax = 0;int rifhtMax = 0;int res = 0;for(int i = 0;i < height.length;i++){leftdp[i] = leftMax = Math.max(height[i],leftMax);}for(int i = height.length-1;i >= 0;i--){rightdp[i] = rifhtMax = Math.max(height[i],rifhtMax);}for(int i = 0;i < height.length;i++){res += Math.min(leftdp[i],rightdp[i]) - height[i]; }return res;}

时间复杂度为O(n)

单调栈

我们发现硅谷处其实也就是发生破坏一个柱子的单调性时,产生了硅谷.我们可以利用这样一个特性完成题目的解题.对于每一个结点的索引,我们存放于栈中,每当这个结点的高度小于栈顶元素的值(也就是需要循环遍历),我们就将其索引值放于栈中.而遇到破坏单调性,也就是一个柱子的高度大于我们的栈顶元素时.我们将栈顶元素弹出,求得此时硅谷处的值.
公式也就是
res += Min(height[peek],height[i])-height[pop]
在这里插入图片描述
需要注意的是

我们应该在栈中无元素时,不用再进行求值,因为此时说明是边界情况,对应此时红框中的情况,当我们计算完pop处之后,下一次循环,我们将弹出peek处的元素,此时它的左边没有元素,也就是对应着此时栈中没有元素.我们不需要再进行求值.

还有一点不同的是,我们遍历处的height[j] 与我们的栈顶元素是有一段宽度的,我们计算面积应该带上宽度的乘积,及宽度长度为 i - peek - 1,对应的情况为
在这里插入图片描述

代码为

public int stack(int[] height){LinkedList<Integer> rain = new LinkedList();int res = 0;for(int i = 0;i < height.length;i++){while(!rain.isEmpty() && height[rain.peek()] < height[i]){int pop = rain.pop();//弹出栈顶元素if(rain.isEmpty()){break;}int left = rain.peek();//获取栈顶元素的值,还在栈中没有弹出int h = Math.min(height[i],height[left]) - height[pop];res += h * (i - left - 1);}rain.push(i);}return res;}

时间复杂度为O(n).

双指针

最后一种解法就是我们的双指针啦,也是最快的解法.不需要开辟任何空间,只需要常量级别的空间,而且只需要一次遍历即可完成.

注意到下标 i 处能接的雨水量由 leftMax[i] 和 rightMax[i] 中的最小值决定。由于数组 leftMax 是从左往右计算,数组 rightMax 是从右往左计算,因此可以使用双指针和两个变量代替两个数组。
遍历过程中,我们更新左右两端的最大值.
当左边的值小于右边的值时,我们直接拿着左边的最大值减去当前结点的高度即可.欸?为什么这里我们不需要再次比较左右两端的最大值,选取其中的较小值呢?
注意啦,我们先判断左边的元素是否大于右边的元素,如果大于我们挪动的是右指针,也就是说明如果右边的值没有大于过左边的值,将一直挪动的是右指针,间接性的把左右两端的最大值作了比较.
右边的值小于左边的值是也是如此.

代码为所以

public int trap(int[] height) {int left = 0;int right = height.length - 1;int leftMax = 0;int rightMax = 0;int res = 0;while(left < right){leftMax = Math.max(leftMax,height[left]);rightMax = Math.max(rightMax,height[right]);if(height[left] < height[right]){res += leftMax - height[left];left++;}else{res += rightMax - height[right];right--;}}return res;}

时间复杂度为O(n),空间复杂度为O(1)

相关文章:

LeetCode42(接雨水)[三种解法:理解动态规划,双指针,单调栈]

接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 这是一道困难题,难度确实有点层次.我们先来朴素思想走一波. 要求能接多少雨水,我们可以具化到每个硅谷,每个硅谷能存多少雨水,那么答案就是每个…...

STM32-ADC+DMA

本内容基于江协科技STM32视频学习之后整理而得。 文章目录 1. ADC模拟-数字转换器1.1 ADC模拟-数字转换器1.2 逐次逼近型ADC1.3 ADC框图1.4 ADC基本结构1.5 输入通道1.6 规则组的转换模式1.6.1 单次转换&#xff0c;非扫描模式1.6.2 连续转换&#xff0c;非扫描模式1.6.3 单次…...

代码随想录算法训练营第六十二天 | 108. 冗余连接、109. 冗余连接II、复习

108. 冗余连接 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1181 文档讲解&#xff1a;https://www.programmercarl.com/kamacoder/0108.%E5%86%97%E4%BD%99%E8%BF… 思路 从前向后遍历每一条边&#xff08;因为优先让前面的边连上&#xff09;&#xff0…...

昇思MindSpore学习笔记6-01LLM原理和实践--FCN图像语义分割

摘要&#xff1a; 记录MindSpore AI框架使用FCN全卷积网络理解图像进行图像语议分割的过程、步骤和方法。包括环境准备、下载数据集、数据集加载和预处理、构建网络、训练准备、模型训练、模型评估、模型推理等。 一、概念 1.语义分割 图像语义分割 semantic segmentation …...

【FFMPEG基础(一)】解码源码

学习分享 main函数decodetorgb32.h 文件decodetorgb32 .cpp文件 main函数 #include <QApplication> #include "decodetorgb32.h" int main(int argc, char *argv[]) {QApplication a(argc, argv);DecodeToRGB32 toRGB32;int restoRGB32.openVideo("../fi…...

第二证券股市资讯:深夜!突然暴涨75%!

一则重磅收买引发医药圈轰动。 北京时间7月8日晚间&#xff0c;美股开盘后&#xff0c;美国生物制药公司Morphic股价一度暴升超75%。音讯面上&#xff0c;生物医药巨子礼来公司官宣&#xff0c;将以57美元/股的价格现金收买Morphic&#xff0c;较上星期五的收盘价溢价79%&…...

flutter 使用wechat_assets_picker的权限检测

https://pub.dev/packages/wechat_assets_picker AssetPicker.pickAssets之前进行权限检查 pickImages() async {try {if (PermissionState.authorized ! await AssetPicker.permissionCheck()) {PermissionUtil.showAllPermissions(Permission.storage, 1);return;}final Lis…...

Mojo入门案例教程(上手篇)

以下是 Mojo 编程语言入门案例教程&#xff0c;内容包括 Mojo 的基本概念、变量、控制结构、函数等方面&#xff1a; Mojo 的基本概念 1.什么是 Mojo&#xff1f;&#xff1a;Mojo 是一种函数式编程语言&#xff0c;用于开发小型应用程序、脚本和工具。 2.Mojo 的特点&#x…...

如何在window执行mkfile

1、Windows cmd中出现错误&#xff1a;“‘make‘ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。”的解决方法_windows_是板栗啊-GitCode 开源社区 2、安装cmder&#xff0c;再通过包管理工具下载make...

Nginx 是一个非常流行的 Web 服务器和反向代理服务器

Nginx 是一个非常流行的 Web 服务器和反向代理服务器&#xff0c;以其高性能、稳定性、丰富的功能集和低资源消耗而闻名。下面是一个简化的 Nginx 使用教程&#xff0c;包括基本的安装、配置和一些常见用途。 安装 Nginx 在 Ubuntu/Debian 上安装&#xff1a; sudo apt upda…...

mysql怎么调整缓冲区大小

MySQL中调整缓冲区大小是数据库性能优化的重要一环。缓冲区大小直接影响了数据库的读写性能和响应速度。以下是一些常见的MySQL缓冲区及其调整方法&#xff1a; 一、InnoDB缓冲池&#xff08;InnoDB Buffer Pool&#xff09; InnoDB缓冲池是InnoDB存储引擎用来缓存表数据和索…...

计算机组成原理学习笔记(一)

计算机组成原理 [类型:: [[计算机基础课程]] ] [来源:: [[B站]] ] [主讲人:: [[咸鱼学长]] ] [评价:: ] [知识点:: [[系统软件]] & [[应用软件]] ] [简单解释:: 管理计算机系统的软件&#xff1b; 按照任务需要编写的程序 ] [问题:: ] [知识点:: [[机器字长]] ] [简单…...

Vue3 对跳转 同一路由传入不同参数的页面分别进行缓存

1&#xff1a;使用场景 从列表页跳转至不同的详情页面&#xff0c;对这些详情页面分别进行缓存 2&#xff1a;核心代码 2.1: 配置路由文件 在路由文件里对需要进行缓存的路由对象添加meta 属性 // 需要缓存的详情页面路由 { name: detail, path: /myRouter/detail…...

LinearLayout的测量流程

在日常开发中我们常常使用LinearLayout作为布局Group&#xff0c;本文从其源码实现出发分析测量流程。大家可以带着问题进入下面的分析流程&#xff0c;看看是否能找到答案。 垂直测量 View的测量入口方法是onmeasure方法。LinearLayout的onMeasure方法根据其方向而做不同的处…...

数据无忧:Ubuntu 系统迁移备份全指南

唠唠闲话 最近电脑出现了一些故障&#xff0c;送修期间&#xff0c;不得不在实验室的台式机上重装系统&#xff0c;配环境的过程花费了不少时间。为避免未来处理类似事情时耗费时间&#xff0c;特此整理一些备份策略。 先做以下准备&#xff1a; U盘启动盘&#xff0c;参考 …...

中国IDC圈探访北京•光子1号金融算力中心

今天&#xff0c;“AI”、“大模型”是最炙手可热的话题&#xff0c;全球有海量人群在工作生活中使用大模型&#xff0c;大模型产品涉及多模态&#xff0c;应用范围已涵盖电商、传媒、金融、短视频、制造等众多行业。 而回看2003年的互联网记忆&#xff0c; “上网”“在线”是…...

[Unity入门01] Unity基本操作

参考的傅老师的教程学了一下Unity的基础操作&#xff1a; [傅老師/Unity教學] Unity3D基礎入門 [華梵大學] 遊戲引擎應用基礎(Unity版本) Class#01 移动&#xff1a;鼠标中键旋转&#xff1a;鼠标右键放大&#xff1a;鼠标滚轮飞行模式&#xff1a;右键WASDQEFocus模式&…...

vivado DELAY_VALUE_XPHY、DIFF_TERM

延迟_值_XPHY PORT对象上的DELAY_VALUE_XPHY属性指定要添加的延迟量 Versal XPHY逻辑接口的输入或输出路径。在的早期阶段 opt_design在重新生成高级I/O向导IP时 DELAY_VALUE_XPHY值将从PORT复制到的XPHY实例上 输入或输出路径。Vivado设计套件中存在DRCs&#xff0c;以确保 DE…...

C++语言相关的常见面试题目(三)

1. List底层实现原理 省流&#xff1a; list底层实现了一个双向循环链表。 每个元素&#xff08;或节点&#xff09;包含三个部分&#xff1a;数据域(_M_Storage)、前驱指针(_M_prev)、后继指针(_M_next)。 数据域&#xff1a;存储实际数据。 前驱指针&#xff1a;指向链表中…...

代码随想录-Day53

739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: …...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...