首页 / 资讯中心 / 文章详情

LeetCode 42题接雨水算法解析与工程应用

LeetCode 42题接雨水算法解析与工程应用 ★ FEATURED ARTICLE
1. 项目概述42接雨水问题的本质42接雨水这个看似神秘的标题实际上源自LeetCode第42题Trapping Rain Water的中文译名。这是一道经典的算法面试题也是实际工程中处理地形数据分析、水资源管理等问题的基础模型。题目描述的是给定n个非负整数表示的高度图每个柱子的宽度为1计算下雨后这个排列能接住多少雨水。我第一次接触这个问题是在2016年参加某大厂面试时面试官在白板上画出几个高低错落的柱子让我计算积水面积。当时我的第一反应是这要怎么算但经过系统学习后才发现这道题考察的是对数据结构、边界条件和计算模型的综合把握能力。在实际应用中类似的算法可以用于预测城市内涝点、设计排水系统甚至计算3D打印物体的最大储水量。2. 核心算法解析与方案对比2.1 暴力解法直观但低效的思考路径最直接的思路是计算每个柱子能接的雨水然后累加。对于每个柱子i找到它左边最高的柱子left_max和右边最高的柱子right_max两者中的较小值减去当前柱子的高度就是该位置的积水量。这种方法时间复杂度O(n²)空间复杂度O(1)。def trap_brute_force(height): total 0 n len(height) for i in range(1, n-1): left_max max(height[:i]) right_max max(height[i1:]) water min(left_max, right_max) - height[i] total max(0, water) return total这个解法在面试中只能算及格分因为当n10⁵时计算量会达到10¹⁰次操作现代计算机需要约1000秒才能完成。我在第一次实现时就踩了这个坑测试用例超时导致笔试失败。2.2 动态规划用空间换时间的优化通过预处理存储每个位置的左右最大值可以将时间复杂度降到O(n)。需要两个数组left_max[i]: 位置i左侧的最高柱子包括iright_max[i]: 位置i右侧的最高柱子包括idef trap_dp(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(left_max[i-1], height[i]) right_max[-1] height[-1] for i in range(n-2, -1, -1): right_max[i] max(right_max[i1], height[i]) total 0 for i in range(n): total min(left_max[i], right_max[i]) - height[i] return total这个版本是我在面试复盘后掌握的空间复杂度O(n)。有趣的是这个算法在实际工程中应用更广因为预处理后的数组可以支持多次查询适合实时降雨量预测系统。2.3 双指针法最优的空间优化方案进一步观察可以发现我们其实不需要存储所有位置的左右最大值。使用左右两个指针向中间移动维护当前的左右最大值即可def trap_two_pointers(height): 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这个算法时间复杂度O(n)空间复杂度O(1)是我现在面试时的首选方案。它的核心思想是积水高度由较矮的一边决定所以可以安全地移动较矮一侧的指针。3. 算法可视化与实际应用3.1 手绘示意图解析假设输入高度为[0,1,0,2,1,0,1,3,2,1,2,1]我们可以这样分析■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 0 1 0 2 1 0 1 3 2 1 2 1积水区域用~表示■ ■~~~■~■~■ ■~~~■~■~■~■~■~■3.2 实际工程应用案例城市排水规划市政工程师使用类似算法分析数字高程模型(DEM)预测暴雨时的积水区域。我曾参与过一个智慧城市项目将算法扩展到三维空间计算建筑群间的雨水径流。农业灌溉设计在梯田灌溉系统中计算每块田地的最大储水量优化水渠布局。以色列的滴灌系统就采用了类似的数学模型。3D打印支撑结构计算打印物体表面可能积存的液体材料避免打印失败。某知名3D打印机厂商的切片软件就内置了这个算法的变种。4. 常见错误与调试技巧4.1 边界条件处理新手常犯的错误包括忘记检查空输入导致数组越界没有处理首尾柱子它们不可能积水积水高度计算未取max(0, value)可能出现负数# 错误示范 def trap_bug(height): total 0 for i in range(len(height)): # 应该从1到n-2 left max(height[:i]) right max(height[i:]) # 应该i1到末尾 total min(left, right) - height[i] # 未处理负数 return total4.2 性能优化技巧提前终止当left_max current_height时可以跳过计算记忆化搜索对重复查询的场景缓存中间结果并行计算大规模数据时分割数组并行处理左右最大值def trap_optimized(height): if len(height) 3: return 0 # 其余优化代码...5. 算法变种与扩展思考5.1 三维接雨水问题这是LeetCode第407题Trapping Rain Water II难度陡增。需要使用最小堆优先处理边界柱子import heapq def trapRainWater(heightMap): if not heightMap: return 0 m, n len(heightMap), len(heightMap[0]) heap [] visited [[False]*n for _ in range(m)] # 初始化边界 for i in range(m): for j in [0, n-1]: heapq.heappush(heap, (heightMap[i][j], i, j)) visited[i][j] True for j in range(1, n-1): for i in [0, m-1]: heapq.heappush(heap, (heightMap[i][j], i, j)) visited[i][j] True # 四个方向 dirs [(-1,0),(1,0),(0,-1),(0,1)] res 0 while heap: h, x, y heapq.heappop(heap) for dx, dy in dirs: nx, ny xdx, ydy if 0nxm and 0nyn and not visited[nx][ny]: res max(0, h - heightMap[nx][ny]) heapq.heappush(heap, (max(h, heightMap[nx][ny]), nx, ny)) visited[nx][ny] True return res5.2 实际工程中的调整非均匀柱宽柱子宽度不同时需要乘以宽度计算体积蒸发渗透因素农业应用中需要考虑时间维度的水分损失实时数据流使用滑动窗口处理连续的传感器数据我在一个农业物联网项目中就遇到过第三种情况最终采用双指针滑动窗口的方案以O(1)空间复杂度实时计算田间积水变化。
阅读完成 · 觉得有帮助?
咨询建站