首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

两种思路的碰撞:从超时分层法到高效双指针的蜕变

  • 25-04-23 05:01
  • 2632
  • 12637
juejin.cn

一、问题回顾:接雨水问题的两种解法对比

题目要求:给定一个非负整数数组表示柱子的高度,计算这些柱子排列后能接多少雨水。

示例分析:
以输入 [0,1,0,2,1,0,1,3,2,1,2,1] 为例,其结构如下:

image.png

可存储 6个单位的雨水。


二、分层法的局限:为何超时?

这里一开始我是想要算出每一层的面积,加起来,然后减去height的总和,剩下的就是水量了。

原思路代码
javascript
代码解读
复制代码
function trap(height) { const n = height.length; if (n === 0) return 0; let totalWater = 0; let h = 1; let left = 0; let right = n - 1; while (true) { while (left < n && height[left] < h) { left++; } while (right >= 0 && height[right] < h) { right--; } // 检查 if (left > right) break; // 计算当前层的有效宽度和统计符合条件的柱子数 const currentWidth = right - left - 1; if (currentWidth <= 0) { h++; continue; } let count = 0; for (let i = left + 1; i < right; i++) { if (height[i] >= h) { count++; } } totalWater += currentWidth - count; h++; } return totalWater; } console.log(trap([0,1,0,2,1,0,1,3,2,1,2,1])); // 6 console.log(trap([4,2,0,3,2,5])); // 9

问题分析:

  1. 时间复杂度高:对于最大高度为 H 的数组,时间复杂度为 O(H * n)。若 H 极大(如 1e5),效率极低。
  2. 重复扫描:每一层都需要重新扫描数组,导致大量冗余计算。

示例缺陷:当输入为 [1e5, 0, 0, ..., 0, 1e5] 时,需要循环 1e5 层,性能无法接受。

所以在最后大量数据示例下运行超时。


三、双指针优化:O(n) 时间的智慧

这里就有夹逼的味道了,也有最短木板的想法。

优化后代码
javascript
代码解读
复制代码
var trap = function(height) { let left = 0, right = height.length - 1; let leftMax = 0, rightMax = 0; let ans = 0; while (left < right) { leftMax = Math.max(leftMax, height[left]); rightMax = Math.max(rightMax, height[right]); if (height[left] < height[right]) { ans += leftMax - height[left]; left++; } else { ans += rightMax - height[right]; right--; } } return ans; };
核心思路
  1. 双指针夹逼:left 和 right 分别从数组两端向中间移动。
  2. 动态维护最大值:
    • leftMax 记录左侧遍历过的最大高度。
    • rightMax 记录右侧遍历过的最大高度。
  3. 水位计算策略:
    • 短板效应:当前水位由左右两侧较小的最大高度决定。
    • 单侧积累:若 height[left] < height[right],则左指针处的水位由 leftMax 决定,反之同理。
正确性证明
  • 局部最优性:每一步移动指针时,总是先处理高度较低的一侧,确保该侧的水位不会超过当前已知的较小最大值。
  • 全局覆盖性:双指针遍历过程中,每个柱子的水位都被其左右两侧的最大值精确覆盖。

四、关键步骤拆解(以示例 1 为例)

ini
代码解读
复制代码
初始状态: left=0, right=11, leftMax=0, rightMax=0, ans=0 Step 1: height[0]=0 < height[11]=1 → 左指针移动 ans += 0 - 0 = 0 → ans=0 left=1 Step 2: leftMax=1(height[1]=1) height[1]=1 < height[11]=1 → 移动左指针 ans += 1 - 1 = 0 → ans=0 left=2 ...(中间步骤省略) 最终累计 ans=6

五、复杂度分析

  • 时间复杂度:O(n),仅需一次遍历。
  • 空间复杂度:O(1),仅需常数空间。

六、方法对比与适用场景

方法时间复杂度适用场景优势
分层双指针法O(H * n)高度较低且分布均匀思路直观,易于理解
优化双指针法O(n)任意高度分布高效,处理大规模数据

image.png

image.png

七、总结

优化后的双指针法通过动态维护左右最大值,将问题转化为单次遍历的线性操作,完美解决了分层法的性能瓶颈。其核心在于利用短板效应和贪心策略,以最小的时间复杂度完成计算。理解这一算法,不仅能够高效解决接雨水问题,更能深入掌握双指针与动态规划的联合应用。

注:本文转载自juejin.cn的海底火旺的文章"https://juejin.cn/post/7495291825064034330"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

104
前端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top