Bootstrap

LeetCode第42题_接雨水

LeetCode 第42题:接雨水

题目描述

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

难度

困难

题目链接

点击在LeetCode中查看题目

示例

示例 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

提示

  • n == height.length
  • 1 <= n <= 2 * 10^4
  • 0 <= height[i] <= 10^5

解题思路

双指针法

这道题可以使用双指针法来解决,核心思想是:对于每个位置能接的雨水量取决于它左右两侧的最大高度中的较小值。

关键点:

  • 每个位置能接的雨水量 = min(左侧最大高度, 右侧最大高度) - 当前高度
  • 使用双指针可以优化空间复杂度,避免存储每个位置的左右最大高度
  • 从两端向中间移动,保证较小的一端已经找到了真实的最大高度

具体步骤:

  1. 使用左右指针分别指向数组两端
  2. 记录左右两侧已遍历部分的最大高度
  3. 每次移动较小的那一侧的指针
  4. 累加当前位置能接的雨水量

图解思路

算法步骤分析表

步骤操作左指针右指针当前接水量说明
初始状态-0110height=[0,1,0,2,1,0,1,3,2,1,2,1]
第一步移动左指针1110左侧高度更小
第二步计算位置12110无法接水
第三步计算位置23111可以接1个单位水

状态/情况分析表

情况输入输出说明
基本情况[0,1,0,2,1,0,1,3,2,1,2,1]6标准情况
单调递增[1,2,3,4,5]0无法接水
对称情况[2,0,2]2中间可以接水

代码实现

C# 实现

public class Solution {
    public int Trap(int[] height) {
        if (height == null || height.Length < 3) return 0;
        
        int left = 0, right = height.Length - 1;
        int leftMax = 0, rightMax = 0;
        int result = 0;
        
        while (left < right) {
            // 更新左右两侧的最大高度
            leftMax = Math.Max(leftMax, height[left]);
            rightMax = Math.Max(rightMax, height[right]);
            
            // 移动较小的一侧
            if (leftMax < rightMax) {
                result += leftMax - height[left];
                left++;
            } else {
                result += rightMax - height[right];
                right--;
            }
        }
        
        return result;
    }
}

执行结果

  • 执行用时:84 ms
  • 内存消耗:41.8 MB

代码亮点

  1. 🎯 使用双指针技巧,实现O(1)空间复杂度
  2. 💡 通过比较左右最大值来决定移动方向,避免重复计算
  3. 🔍 处理边界情况:数组长度小于3时直接返回0
  4. 🎨 代码结构简洁,逻辑清晰,易于理解

常见错误分析

  1. 🚫 没有处理数组为空或长度不足的边界情况
  2. 🚫 错误计算最大高度,导致结果偏大
  3. 🚫 移动指针的条件判断错误
  4. 🚫 忘记更新最大高度值

解法对比

解法时间复杂度空间复杂度优点缺点
暴力法O(n²)O(1)思路简单效率低
动态规划O(n)O(n)直观易懂空间复杂度高
双指针法O(n)O(1)最优解理解稍难

相关题目

;