资讯详情

接雨水问题:从暴力解法到双指针优化

📅 2026/10/26 20:04:28 | 华诺云谱 👁 阅读
接雨水问题:从暴力解法到双指针优化
1. 问题背景与核心思路接雨水问题是算法领域经典的二维平面问题题目描述如下给定n个非负整数表示每个宽度为1的柱子的高度图计算按此排列的柱子能接多少雨水。这道题在力扣题库中编号为42题属于高频面试题考察对数组、双指针和动态规划的综合运用能力。我第一次接触这个问题时直观想到的是每个柱子能接的水量取决于左右两侧最高柱子的较小值。比如对于高度为[0,1,0,2,1,0,1,3,2,1,2,1]的柱子序列雨水会积聚在低洼处。这个观察直接引出了暴力解法的思路——对于每个柱子分别向左向右遍历找到最高柱子然后取两者较小值减去当前柱子高度。2. 暴力解法实现与优化2.1 基础暴力解法最直接的实现方式是双层循环def trap(height): total 0 n len(height) for i in range(n): max_left max_right 0 # 向左找最大值 for j in range(i, -1, -1): max_left max(max_left, height[j]) # 向右找最大值 for j in range(i, n): max_right max(max_right, height[j]) total min(max_left, max_right) - height[i] return total这个解法时间复杂度O(n²)空间复杂度O(1)。在实际面试中这种解法虽然能通过部分测试用例但对于大规模数据会超时。2.2 预处理优化观察到每次都要重复计算左右最大值可以预先存储def trap(height): if not height: return 0 n len(height) left_max [0] * n right_max [0] * n left_max[0] height[0] for i in range(1, n): left_max[i] max(height[i], left_max[i-1]) right_max[-1] height[-1] for i in range(n-2, -1, -1): right_max[i] max(height[i], right_max[i1]) total 0 for i in range(n): total min(left_max[i], right_max[i]) - height[i] return total优化后时间复杂度O(n)空间复杂度O(n)。这是典型的空间换时间策略在面试中已经是可以接受的解法。3. 双指针的巧妙解法3.1 双指针核心思路更优的解法是使用双指针将空间复杂度降到O(1)def trap(height): if not height: return 0 left, right 0, len(height) - 1 left_max right_max 0 total 0 while left right: if height[left] height[right]: if height[left] left_max: left_max height[left] else: total left_max - height[left] left 1 else: if height[right] right_max: right_max height[right] else: total right_max - height[right] right - 1 return total这个解法的精妙之处在于当height[left] height[right]时我们确信left_max一定小于等于当前的right_max因为right指针还没移动所以可以直接计算left位置的水量。3.2 双指针的移动策略关键在于理解指针移动的条件当左侧柱子较矮时处理左侧水量并右移指针当右侧柱子较矮时处理右侧水量并左移指针每次移动较矮的一侧确保另一侧有更高的柱子挡水这种策略保证了我们总是在已知左右边界的情况下计算当前柱子的积水量。4. 单调栈解法4.1 单调栈的应用场景对于接雨水问题单调栈提供了一种不同的视角def trap(height): stack [] total 0 for i in range(len(height)): while stack and height[i] height[stack[-1]]: top stack.pop() if not stack: break distance i - stack[-1] - 1 bounded_height min(height[i], height[stack[-1]]) - height[top] total distance * bounded_height stack.append(i) return total单调栈维护一个递减的柱子高度序列当遇到更高的柱子时说明可能形成洼地可以计算积水。4.2 单调栈的工作流程初始化空栈遍历每个柱子当栈不为空且当前柱子高于栈顶柱子时弹出栈顶作为洼地底部计算新栈顶与当前柱子形成的边界计算积水面积并累加将当前柱子索引入栈这种方法特别适合处理局部洼地的积水计算时间复杂度O(n)空间复杂度O(n)。5. 不同解法的对比分析解法类型时间复杂度空间复杂度适用场景编码难度暴力解法O(n²)O(1)小规模数据简单预处理O(n)O(n)一般情况中等双指针O(n)O(1)最优解较难单调栈O(n)O(n)特殊需求中等在实际面试中建议优先实现双指针解法它综合了时间效率和空间效率。如果面试官要求解释其他解法可以依次介绍预处理和单调栈方法。6. 常见错误与调试技巧6.1 边界条件处理容易忽略的特殊情况包括空数组输入单调递增/递减的柱子序列所有柱子高度相同只有两个柱子的情况提示在编写代码前先考虑这些边界情况可以避免很多错误。6.2 计算逻辑错误常见错误有忘记减去当前柱子的高度左右最大值计算错误指针移动条件判断错误积水宽度计算错误在单调栈解法中调试时可以打印中间变量print(fi{i}, left_max{left_max}, right_max{right_max}, total{total})6.3 性能优化技巧对于大规模数据避免不必要的重复计算尽量使用迭代而非递归合理使用提前终止条件选择合适的数据结构7. 实际应用与变种问题接雨水问题的思想可以应用于三维接雨水问题容器盛水问题地形分析流量计算变种问题包括使用柱子围成的最大面积类似力扣11题接雨水后的柱子高度分布允许柱子本身有宽度的情况我在实际工作中发现这类问题的解决思路可以迁移到很多资源分配和容量规划的场景中。比如在云计算资源调度时如何平衡不同节点的负载就与接雨水的思想类似。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑