面试经典算法150题系列-接雨水

接雨水

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

示例 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. 双指针:使用两个指针 leftright 分别从数组的两端向中间遍历。这样可以同时考虑左右两边的柱子高度。

  3. 维护最大高度:在遍历过程中,维护两个变量 leftMaxrightMax 来记录从左边和右边开始遍历到目前为止遇到的最高的柱子高度。

  4. 计算雨水量:当遍历到的柱子高度小于 leftMaxrightMax 时,可以计算出当前柱子能接的雨水量,即 min(leftMax, rightMax) - height[i]。如果柱子高度大于等于记录的最大高度,则更新 leftMaxrightMax

  5. 累加雨水量:将每次计算出的雨水量累加到总雨水量 ans 中。

  6. 边界条件:如果输入数组为空或长度为0,则直接返回0,因为没有柱子可以接雨水。

具体步骤如下:

  1. 初始化两个指针 leftright 分别指向数组的开始和结束位置,以及两个变量 leftMaxrightMax 为0。

  2. 使用一个循环,当 left 小于 right 时继续执行:

    • 如果 height[left] < height[right],则移动 left 指针,并更新 leftMax
      • 如果当前柱子高度大于等于 leftMax,则更新 leftMax
      • 否则,计算当前柱子能接的雨水量,并累加到 ans
    • 否则,移动 right 指针,并更新 rightMax:类似地更新 rightMax 和累加雨水量。
  3. leftright 相遇时,遍历结束,返回计算出的总雨水量 ans

这种双指针的方法时间复杂度为 O(n),其中 n 是数组 height 的长度,因为每个元素只被遍历一次。空间复杂度为 O(1),因为只需要常数级别的额外空间。

思路模拟:

让我们通过一个模拟来更深入地理解接雨水问题的解决思路。假设我们有以下高度数组:

height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]

我们的目标是找到这些柱子之间可以接多少雨水。下面是一步步的模拟过程:

  1. 初始化两个指针 leftright 分别指向数组的两端,即 left = 0right = length - 1。同时,初始化两个变量 leftMaxrightMax 来记录左右两边遍历过程中的最大高度,初始值设为0。

  2. 遍历开始:

    • 当 left < right 时,执行循环。
    • 比较 height[left] 和 height[right]
      • 如果 height[left] < height[right],说明我们处于左侧的较低部分,我们需要更新 leftMax 并可能计算左侧的雨水量。
      • 如果 height[left] >= height[right],我们处于右侧的较低部分或两边高度相同,更新 rightMax 并可能计算右侧的雨水量。
  3. 在每一步中,我们执行以下操作:

    • 如果当前柱子的高度小于 leftMax,则当前柱子可以接到雨水,雨水量为 leftMax - height[left]
    • 如果当前柱子的高度大于或等于 leftMax,则更新 leftMax 为当前柱子的高度。
  4. 同理,对于右侧:

    • 如果 height[right] < height[left],则 rightMax 可能更新,并且可能计算右侧的雨水量。
    • 如果 height[right] 更新了 rightMax,则不会立即计算雨水,因为只有在移动到更矮的柱子时才会计算。
  5. 重复步骤3和4,直到 leftright 相遇。

  6. 累加每一步计算的雨水量,得到最终结果。

让我们模拟这个过程:

  • 初始状态:left = 0right = 12leftMax = 0rightMax = 0ans = 0
  • 移动 left 到下一个元素,leftMax 更新为1(height[1])。
  • 移动 right 到前一个元素,rightMax 更新为1(height[12])。
  • 继续移动 left 和 right,更新 leftMax 和 rightMax,直到它们指向相邻的元素。

下面是模拟的详细步骤:

left:          0  1  2  3  4  5  6  7  8  9 10 11 12 (right)
height:     0  1  0  2  1  0  1  3  2  1  2  1   0
leftMax:   0  1  1  2  2  2  3  3  3  2  2  1   1
rightMax: 0  0  0  0  1  1  1  2  3  3  2  1   1
ans:         0  0  0  2  3  4  4  5  6  6  5  4   3

在每一步,我们可以看到 leftMaxrightMax 的更新,以及计算的雨水量累加到 ans 中。最终,ans 的值是6,这就是我们可以接到的雨水总量。

请注意,这个模拟是为了演示算法的逻辑流程,实际的代码实现会使用条件语句来确定何时更新 leftMaxrightMax 以及何时计算雨水量。

实现代码:

public int trap(int[] height) {if (height == null || height.length == 0) {return 0;}int n = height.length;int left = 0, right = n - 1;int leftMax = 0, rightMax = 0;int ans = 0;while (left < right) {if (height[left] < height[right]) {// 当左边的柱子高度小于右边的柱子高度if (height[left] >= leftMax) {// 更新左边的柱子能接的雨水量leftMax = height[left];} else {// 计算当前柱子能接的雨水量,并累加到总雨水量中ans += leftMax - height[left];}left++;} else {// 右边的柱子高度不小于左边的柱子高度if (height[right] >= rightMax) {// 更新右边的柱子能接的雨水量rightMax = height[right];} else {// 计算当前柱子能接的雨水量,并累加到总雨水量中ans += rightMax - height[right];}right--;}}return ans;}

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

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

相关文章

doxygen制作接口文档

系列文章目录 文章目录 系列文章目录前言一、下载二、安装三、代码注释四、使用doxygen生成文档 前言 每次手动写接口文档太痛苦了&#xff0c;现在福利来了–doxygen Doxygen是软件开发中广泛使用的文档生成器工具。它自动从源代码注释生成文档&#xff0c;解析有关类、函数和…

LVS原理详解及部署

目录 一、LVS原理 1.LVS简介 2.LVS结构 3.IP负载均衡技术 4.LVS相关术语 二、LVS负载均衡四种工作模式 1.LVS-DR模式 2.LVS-NAT模式 3.LVS-TUN模式&#xff08;了解&#xff09; 4.FULL-NAT模式&#xff08;了解&#xff09; 三、LVS负载均衡十种调度算法 四、LVS部…

学习大数据DAY35 利用 echarts 的开源图表和 python 异常处理优化网站

目录 根据分数统计电影数量来生成图表 上机练习 14 添加异常 添加电影类型判断是整数及正整数异常 部署项目到 Nginx 上机练习 15 根据分数统计电影数量来生成图表 Echarts 官网&#xff1a; https://echarts.apache.org/examples/zh/index.html 下载柱状图和饼图 可以…

Java Enum类笔记

Java系列文章目录 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;五、总结&#xff1a;5.1 学习总结&#xff1a; 一、前言 学习Enum类的笔记 二、学习内容&#xff1a; Eunm类的实操 三、问题描述 Eunm枚举的使用 四、解…

Datawhale X 魔搭 AI夏令营第四期-魔搭生图task1学习笔记

根据教程提供的链接&#xff0c;进入相应文章了解魔搭生图的主要工作是通过对大量图片的训练&#xff0c;生成自己的模型&#xff0c;然后使用不同的正向、反向提示词使模型输出对应的图片 1.官方跑baseline教程链接:Task 1 从零入门AI生图原理&实践 2.简单列举一下赛事的…

MongoDB教程

目录 介绍启动命令命令行操作常用命令总结MongoDB Compass 介绍 MongoDB是一个基于分布式文件存储的开源数据库系统&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB将数据存储为一个文档&#xff0c;数据结构由键值对组成&…

ibis:极具潜力的Python数据分析新框架

今天要给大家介绍的Python框架叫做ibis&#xff0c;没错&#xff0c;跟著名连锁酒店宜必思同名&#xff0c;其作者是创造了pandas、Arrow等著名框架的Wes McKinney。 ibis的核心理念是用同一套数据框操作API&#xff0c;统一操纵各种主流的数据运算框架&#xff0c;使得用户可以…

Ubuntu安装 IDEA

一、在官网下载 IDEA 下载IDEA For LinuxDownload the latest version of IntelliJ IDEA for Windows, macOS or Linux.https://www.jetbrains.com/idea/download/?sectionlinux下载好的安装包解压到/opt/中&#xff0c;目录名更改为 idea 二、对/opt/idea 目录下所有文件授予…

canal监听mysql增量数据发布到rabbitmq

canal工作原理 canal 依靠mysql主从备份的原理&#xff0c;模拟 MySQL slave 的交互协议&#xff0c;伪装自己为 MySQL slave &#xff0c;向 MySQL master 发送dump 协议MySQL master 收到 dump 请求&#xff0c;开始推送 binary log 给 slave (即 canal )canal 解析 binary …

C++11右值引用

什么是左值&#xff0c;什么是右值&#xff1f; 不可以单纯字面去理解&#xff0c;等号左边是左值&#xff0c;等号右边是右值。 左值&#xff1a;可以修改的可以认为是左值&#xff0c;左值通常是变量。 右值&#xff1a;通常是常量&#xff0c;表达式或函数返回值&#xff0…

浅谈C/C++指针和引用在Linux和Windows不同环境下的编码风格

目录 0. 前言 1. 代码块、函数体上的 { } 的规范 2. 指针和引用中的 * 和 & 符号的位置 1. Linux 环境下编码风格(gcc) 2. Windows 环境下编码风格(Visual Studio) 3. 简单总结 0. 前言 C/C因为高度的自由性&#xff0c;并没有对一些常见的编码风格进行限制&#…

Hive3:数据的加载与导出

一、加载数据 在创建表之后&#xff0c;表中没有数据&#xff0c;我们不可能insert存入数据。 而是&#xff0c;通过数据加载&#xff0c;将HDFS中的数据关联到Hive表中。 建表 CREATE TABLE myhive.test_load(dt string comment 时间&#xff08;时分秒&#xff09;, user_…

某客户ODS数据库undo段问题分析处理

概述 ODS数据库在7月22日4个时间点02:03,05:17,07:04,08:53分别报如下错误&#xff1a; 原因分析 Ora-1628&#xff1a;max # extents 32765 reached for rollback segment _SYSSMU19990_761259507$ Oracle 官方解释&#xff1a; Cause: An attempt was made to extend a roll…

VScode:前端项目中导出和导入插件

# 终端运行&#xff1a;导出扩展插件到指定路径&#xff08;txt&#xff09; code --list-extensions > C:\Users\UserName\Documents\extensions.txt # 终端运行&#xff1a;导入指定路径&#xff08;txt&#xff09;的扩展插件 Get-Content C:\Users\UserName\Documen…

渗透测试实战-菠菜站渗透测试(Nacos反序列化漏洞利用)

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

Python 设计模式之工厂函数模式

文章目录 案例基本案例逐渐复杂的案例 问题回顾什么是工厂模式&#xff1f;为什么会用到工厂函数模式&#xff1f;工厂函数模式和抽象工厂模式有什么关系&#xff1f; 工厂函数模式是一种创建型设计模式&#xff0c;抛出问题&#xff1a; 什么是工厂函数模式&#xff1f;为什么…

uniapp版本更新除了plus.runtime.getProperty的解决办法

以下是展示图 带尺寸的图片: 首先把以下代码放到想要更新弹出的页面 //template部分<uni-popup ref"popup" background-color"#fff"><versionUp handleCloseVersion"closeVersion"></versionUp></uni-popup>//script…

应急响应:Windows 入侵排查思路.

什么是应急响应. 一个组织为了 应对 各种网络安全意外事件的发生 所做的准备 以及在 事件发生后 所采取的措施 。说白了就是别人攻击你了&#xff0c;你怎么把这个攻击还原&#xff0c;看看别人是怎么攻击的&#xff0c;然后你如何去处理&#xff0c;这就是应急响应。 目录&am…

上海电信万兆宽带2026年将实现全城覆盖

为了响应号召&#xff0c;上海力争到2026年&#xff0c;初步建成以5G-A和万兆光网为标志的全球双万兆城市。上海电信正式对外宣布将于8月30日正式上线“美好家万兆融合套餐”&#xff0c;同时发布速率行业领先的“5G-A套餐”&#xff0c;上线“随翼选”云翼智选礼包&#xff0c…

【Go】手写简易go webserver

核心&#xff1a;实现net/http库中handler接口的ServeHTTP方法的实例&#xff0c;通过http.ListenAndServe注册后&#xff0c;所有的请求都会打到该实例的ServeHTTP方法里。Context是对请求对象和响应对象的封装&#xff0c;实现了获取请问请求参数、设置状态码、设置响应头、设…