力扣 42. 接雨水 - 高效双指针解法(Rust实现)详细题解

rust 复制代码
impl Solution {
    pub fn trap(height: Vec<i32>) -> i32 {
        if height.len()<3{
           return 0;
      }
    let mut left = 1;
    let mut right = height.len()-2;

    let mut leftmax = height[0];
    let mut rightmax = height[right+1];

    let mut res = 0;

    while left<=right{
        leftmax = leftmax.max(height[left]);
        rightmax = rightmax.max(height[right]);

        if leftmax<rightmax {
            res+=leftmax-height[left];
            left+=1;
        }else{
            res+=rightmax - height[right];
            right-=1;
        }
    }
    res
 }
}

💡 核心思想:木桶效应

要计算整个地形能接多少雨水,我们可以按 来计算。对于任意一列 i,它能接住的雨水量取决于:
它左边最高的柱子(leftmax)它右边最高的柱子(rightmax)较矮的那一个。

这就是经典的"木桶效应":
第 i 列的雨水量 = min(leftmax, rightmax) - height[i]
(注意:如果计算结果小于0,说明这列本身就是最高的,接不到水,记为0)

如果采用暴力或动态规划,我们需要 O(N)O(N) 的额外空间来存储每个位置的左右最大值。而双指针法通过在两端向中间逼近,巧妙地将空间复杂度降到了 O(1)O(1)。


🚀 代码逐段原理解析

1. 边界防御,防止越界

复制代码
if height.len() < 3 {
    return 0;
}

接雨水至少需要 3 根柱子(两边高,中间低)才能形成凹槽。这个前置判断不仅是逻辑优化,更重要的是保护了后续代码 。因为下面用到了 height.len() - 2,如果不拦截长度小于 3 的情况,在 Rust 中会因为 usize 溢出而引发 Panic。

2. 指针初始化

复制代码
let mut left = 1;
let mut right = height.len() - 2;

let mut leftmax = height[0];
let mut rightmax = height[right + 1]; // 即 height[height.len() - 1]

这是一个非常棒的细节优化!

最左侧 height[0] 和最右侧 height[len-1] 作为边界,它们上面是绝对不可能积水的。

所以你直接将它们作为初始的 leftmaxrightmax,并将 leftright 指针向内收缩一位(从 1len-2 开始遍历)。这省去了对无效边界的计算。

3. 双指针的核心

复制代码
while left <= right {
    // 1. 同步更新当前左右两侧的最大高度
    leftmax = leftmax.max(height[left]);
    rightmax = rightmax.max(height[right]);

    // 2. 比较 leftmax 和 rightmax,决定处理哪一边
    if leftmax < rightmax {
        res += leftmax - height[left];
        left += 1;
    } else {
        res += rightmax - height[right];
        right -= 1;
    }
}

这是整个算法的灵魂所在,为什么可以这样写?

  • 为什么可以只看一边的最大值?
    假设当前 leftmax < rightmax,对于 left 指针所在的位置来说,它的左侧最高确定是 leftmax。虽然它的右侧可能还有比 rightmax 更高的柱子,但这已经不重要了 ,因为"木桶"的短板已经确定是 leftmax。因此,我们可以放心地计算 left 处的积水量,并将 left 指针向右移。反之亦然。
  • 如何避免负数积水?
    注意这行代码:leftmax = leftmax.max(height[left]);
    因为你在计算积水 leftmax - height[left] 之前 ,先更新了 leftmax。这就保证了 leftmax 永远大于等于当前的 height[left]。如果当前柱子是迄今为止最高的,leftmax 就会等于 height[left],相减得 0,完美符合物理现实(高山顶上不积水),无需写繁琐的 if 去防止负数。

📊 复杂度分析

  • 时间复杂度:O(N)O(N)
    其中 NN 是数组 height 的长度。leftright 指针相向而行,每个元素最多被访问一次,整个过程只有一次遍历。
  • 空间复杂度:O(1)O(1)
    只使用了 leftrightleftmaxrightmaxres 等几个标量类型的变量,没有开辟额外的数组空间。空间复杂度达到了理论最优。
相关推荐
qq_85730581922 分钟前
python语法
开发语言·python·算法
DXM052140 分钟前
第9期|从机器学习到深度学习:AI遥感解译的进化逻辑
人工智能·算法·计算机视觉
小蒋学算法1 小时前
算法-阶乘函数后K个零
算法
weixin_307779131 小时前
智能模拟数据生成平台:生成式AI合成数据技术重塑开发测试效能
人工智能·测试工具·算法·测试用例
阿正的梦工坊2 小时前
【Rust】04-借用、引用与切片
java·数据库·rust
福大大架构师每日一题2 小时前
2026年6月TIOBE编程语言排行榜,Go语言排名第13,Rust语言排名12。关于Rust已进入平台期的报道似乎为时过早。
开发语言·golang·rust
羊羊小栈2 小时前
Uplift营销供应链协同决策系统(基于Uplift因果推断与运筹优化算法)
前端·人工智能·算法·毕业设计·大作业
咸甜适中2 小时前
rust语言学习笔记Trait(十六)Error(错误)
笔记·学习·rust
guyoung2 小时前
BoxAgnts 工具系统(4)——Tool Trait 与并发上下文模型
rust·agent·ai编程
金融小师妹2 小时前
AI因子共振模型显示:金银比突破区间上沿,白银定价逻辑进入再校准阶段
人工智能·算法·均值算法·线性回归