LeetCode 42. 接雨水(C语言详解)——双指针经典解法

一、题目描述

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

示例 1:

复制代码
输入:
height = [0,1,0,2,1,0,1,3,2,1,2,1]

输出:
6

解释:

该高度图在下雨后可以接到 6 个单位的雨水。

示例 2:

复制代码
输入:
height = [4,2,0,3,2,5]
输出:
9

二、问题分析

每个位置能接多少雨水,取决于:

复制代码
min(左侧最高柱子, 右侧最高柱子) - 当前柱子高度

例如:

复制代码
      █
  █   █
█ █ █ █

如果某一位置:

复制代码
左边最高 = 4
右边最高 = 3
当前高度 = 1

那么该位置可以接的水为:

复制代码
min(4,3) - 1 = 2

三、双指针解法(最优解)

为了高效计算,我们可以使用 双指针 + 动态维护左右最大值。

定义两个指针:

复制代码
left  = 0
right = n - 1

同时维护:

复制代码
leftMax  = 左侧最大高度
rightMax = 右侧最大高度

核心思想:

  • 如果 height[left] < height[right]

    • 说明左侧是短板

    • 用 leftMax 计算水量

  • 否则

    • 右侧是短板

    • 用 rightMax 计算水量

因为水位始终取决于 较矮的一侧。


四、算法流程

  1. 初始化指针

    left = 0
    right = n - 1

  2. 记录左右最大高度

    leftMax = 0
    rightMax = 0

  3. 遍历数组

    while(left < right)

  4. 判断左右高度关系

若:

复制代码
height[left] < height[right]

更新左侧:

复制代码
leftMax = max(leftMax, height[left])

water += leftMax - height[left]

否则更新右侧:

复制代码
rightMax = max(rightMax, height[right])

water += rightMax - height[right]
  1. 移动指针

直到 left >= right。


五、C语言代码实现

复制代码
int trap(int* height, int heightSize) {

    int left = 0;
    int right = heightSize - 1;

    int leftMax = 0;
    int rightMax = 0;

    int water = 0;

    while (left < right) {

        if (height[left] < height[right]) {

            if (height[left] >= leftMax)
                leftMax = height[left];
            else
                water += leftMax - height[left];

            left++;

        } else {

            if (height[right] >= rightMax)
                rightMax = height[right];
            else
                water += rightMax - height[right];

            right--;
        }
    }

    return water;
}

六、复杂度分析

复杂度 说明
时间复杂度 O(n)
空间复杂度 O(1)

只遍历一次数组,并且没有使用额外数组空间。


七、示例分析

输入:

复制代码
height = [0,1,0,2,1,0,1,3,2,1,2,1]

计算过程会累计得到:

复制代码
1 + 1 + 2 + 1 + 1 = 6

最终结果:

复制代码
6

八、总结

本题是 经典的双指针问题,核心思想是:

复制代码
水位 = min(左侧最高柱子, 右侧最高柱子)

通过双指针不断向中间收缩,并动态维护 leftMax 和 rightMax,就可以在 O(n) 时间内计算出所有雨水量。

这种方法相比使用 leftMax[] 和 rightMax[] 数组的解法,空间复杂度从 O(n) 降到了 O(1),是面试中更推荐的写法。

相关推荐
moshuying2 小时前
块扩散 + GDN 改造:Clover 把「并行生成」塞进了 Agent 的长上下文里
前端·算法
没落之王2 小时前
历史系统建模:宋初太祖太宗「再立天庭」秩序重构推演
人工智能·算法·重构
INGNIGHT3 小时前
91 · 最小调整代价(序列dp)
数据结构·算法·leetcode
moshuying3 小时前
扩散模型开始写代码、开网页了:350 亿参数,速度比 Jev 快一倍
前端·算法
小超人诞生日记3 小时前
C++ 异常机制详解:从抛出捕获到异常安全
c++·算法
多弗朗皮卡丘3 小时前
C++的IO流
开发语言·c++·io流·文件io流
labuladong4 小时前
机器学习&神经网络 系列教程上线
神经网络·算法·机器学习
xiangyun614 小时前
C++ 手撕 shared_ptr:引用计数与控制块到底长什么样?
开发语言·c++·算法·面试·stl
学习论之费曼学习法4 小时前
无人值守AI内容矩阵实战(8):标题 A/B 实验的 6 个工程实现细节,隔日对比与自动判胜
人工智能·python·算法·矩阵·自动化·a/b测试·内容矩阵
Carl_奕然4 小时前
【机器视觉】最强算法之:3D高斯泼溅(3D Gaussian Splatting)
人工智能·python·算法·目标检测·计算机视觉·3d