0

0

C++怎么实现接雨水算法_C++双指针与单调栈【算法】

穿越時空

穿越時空

发布时间:2026-02-24 10:19:37

|

101人浏览过

|

来源于php中文网

原创

双指针降时间复杂度至o(n),关键在按较矮侧已知最大值计算当前水量;常见错误是移动指针后立即更新max,正确顺序为:先算水、再更新max、最后移指针。

c++怎么实现接雨水算法_c++双指针与单调栈【算法】

为什么双指针比暴力解法快,但容易错在边界更新逻辑

双指针解法核心是避免对每个位置都扫全数组找左右最大值,时间从 O(n²) 降到 O(n)。关键不在“两个指针”,而在“谁决定当前能接多少水”——取决于较矮那边的已知最大值。

常见错误是写成:left++right-- 后立刻用新位置的 height[left] 更新 left_max,导致用还没验证过的值参与计算。正确顺序必须是:先用旧 left_max 算当前格子的水量,再更新 left_max,最后移动指针。

  • 移动指针前,先用当前 left_maxright_max 计算 min(left_max, right_max) - height[i]
  • 只有当 height[left] 时才动 <code>left,因为此时 left 处的瓶颈由 left_max 决定,right_max 是冗余信息
  • left_max 必须用 max(left_max, height[left]) 更新,不是直接赋值;否则会丢失历史峰值

单调怎么存“可能被填满的坑”,而不是存高度值本身

单调栈在这里不是为了排序,而是维护一个“待结算的左侧下降沿”。栈里存的是下标,不是高度值——因为要算宽度(i - stack.top() - 1)和高度差(min(height[stack.top()-1], height[i]) - height[stack.top()])。

典型误操作是把栈设成 stack<int></int> 却往里 push 高度值,结果算宽度时完全没法定位。另一个坑是 while 循环条件写成 !st.empty() && height[i] > height[st.top()],漏了栈空检查,导致 st.top() 崩溃。

立即学习C++免费学习笔记(深入)”;

360AI导航
360AI导航

360导航旗下的AI网址导航站,精选互联网资源最全的AI人工智能网站

下载
  • 栈类型必须是 stack<int></int>,存下标,别存 int
  • while 条件要写全:!st.empty() && height[i] > height[st.top()],不能省略 !st.empty()
  • 每次 pop 后,必须确保栈非空才能取新的 st.top() 作为左边界,否则跳过这次结算

两种方法在空洞嵌套场景下的行为差异

比如输入 [3,2,1,2,3],中间 [2,1,2] 是个“小盆地”,双指针会把它当作独立单元处理;而单调栈会在遇到第二个 2 时,一次性把 1 和第一个 2 都弹出,再分别结算。这不是对错问题,而是抽象视角不同:双指针是“逐格推演”,单调栈是“按坑结算”。

性能上,双指针常数更小、缓存友好;单调栈多一次遍历+栈操作,但在需要记录每个坑的左右边界时(比如扩展成“最大矩形”),栈结构天然支持。

  • 双指针无法直接回答“哪一段构成了某个积水区域”,它只累计总量
  • 单调栈每 pop 一次,就确定了一个以弹出下标为底部、左右为边界的积水块
  • 如果输入含大量平台(连续相等高度),双指针仍稳定;单调栈需注意相等时是否入栈——通常 >= 才入栈,避免重复结算

别忽略 height 为空或单元素时的边界

几乎所有实现都会在开头加 if (height.size() ,但很多人写成 <code>height.empty() || height.size() == 1,漏了 size() == 2 的情况。两个柱子根本没法存水,必须排除。

另一个隐形坑是用 vector<int>::size_type</int> 做循环变量,和负数比较(比如 i >= 0)时触发无符号整数回绕,导致死循环。C++ 中优先用 int i 配合 static_cast<int>(height.size())</int>

  • 安全判断写法:if (height.size() ,别拆开写
  • 双指针初始化时,left = 0, right = height.size() - 1,必须保证 rightint 类型,不是 size_t
  • 单调栈循环中,iint,不要依赖 auto i : ...,防止类型推导出错

事情说清了就结束。最常掉进去的地方不是算法逻辑,是下标越界、类型混用、还有把“能存水”和“当前格子存多少”搞混。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

828

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

103

2023.09.25

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

850

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

581

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

210

2025.08.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

422

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

595

2023.08.10

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1228

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号