力扣解题-接雨水

力扣解题-接雨水

给定 n 个非负整数表示每个宽度为 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 * 104

0 <= heighti <= 105

Related Topics

数组

双指针

动态规划

单调栈


第一次解答

解题思路

核心方法:动态规划预处理左右最大高度 + 逐列计算接水量,通过提前预存每个位置左右两侧的最大柱子高度,将"找左右最大高度"的时间复杂度从O(n)降至O(1),整体时间复杂度优化至O(n),是接雨水问题的经典高效解法。

具体步骤:

  1. 核心原理铺垫 :每个位置i能接住的雨水量 = min(位置i左侧最大高度, 位置i右侧最大高度) - 位置i自身高度(若结果为正,否则接水量为0)。这是因为雨水的高度由左右两侧更矮的"挡板"决定,且只有当挡板高度高于当前柱子时,才能接住雨水。
  2. 预处理左侧最大高度数组maxLeft
    • 初始化长度与height相同的数组maxLeftmaxLeft[i]表示位置i左侧(不包含i)的最大柱子高度。
    • 从左到右遍历数组(起始下标i=1,因为下标0左侧无柱子):maxLeft[i] = Math.max(maxLeft[i-1], height[i-1]),即当前位置的左侧最大高度 = 前一位置的左侧最大高度 和 前一位置柱子高度 的较大值,通过递推完成所有位置的左侧最大高度计算。
  3. 预处理右侧最大高度数组maxRight
    • 初始化长度与height相同的数组maxRightmaxRight[i]表示位置i右侧(不包含i)的最大柱子高度。
    • 从右到左遍历数组(起始下标i=height.length-2,因为最后一个位置右侧无柱子):maxRight[i] = Math.max(maxRight[i+1], height[i+1]),即当前位置的右侧最大高度 = 后一位置的右侧最大高度 和 后一位置柱子高度 的较大值,通过递推完成所有位置的右侧最大高度计算。
  4. 逐列计算总接水量
    • 初始化总接水量sum=0,遍历数组中除首尾外的所有位置i(首尾位置无两侧挡板,无法接水)。
    • 对每个位置i,计算左右最大高度的较小值min = Math.min(maxLeft[i], maxRight[i])
    • min > height[i],说明当前位置能接水,接水量为min - height[i],将其累加到sum;若min <= height[i],则接水量为0,无需处理。
  5. 返回结果 :遍历完成后,sum即为所有位置能接住的雨水总量,返回该值。

核心优化逻辑说明

  1. 时间复杂度优化 :若不预处理左右最大高度,直接对每个位置遍历左右找最大值,时间复杂度为O(n²)(每个位置找左右最大值各需O(n)),无法适配n=2×10⁴的规模;动态规划预处理仅需两次O(n)遍历,后续逐列计算为O(n),整体时间复杂度为O(n),完全满足题目性能要求。
  2. 空间复杂度说明:该解法用两个长度为n的数组存储左右最大高度,空间复杂度为O(n),这是"时间换空间"的典型应用------通过额外的O(n)空间开销,换取时间复杂度从O(n²)到O(n)的质的提升。
  3. 性能表现说明:
    • 耗时5ms击败32.91%的用户:动态规划解法是接雨水的标准解法之一,多数提交均采用此逻辑,耗时差异主要来自评测机运行环境,该耗时已属于高效范畴;
    • 内存消耗76MB击败19.06%的用户:核心原因是额外创建了两个长度为n的数组,若需优化内存,可改用双指针法(空间复杂度O(1)),但逻辑复杂度会略有提升。

执行耗时:1 ms,击败了83.92% 的Java用户

内存消耗:47.9 MB,击败了15.52% 的Java用户

java 复制代码
public int trap(int[] height) {
        int sum = 0;
        int[] maxLeft = new int[height.length];
        int[] maxRight = new int[height.length];

        for (int i = 1; i < height.length - 1; i++) {
            maxLeft[i] = Math.max(maxLeft[i - 1], height[i - 1]);
        }
        for (int i = height.length - 2; i >= 0; i--) {
            maxRight[i] = Math.max(maxRight[i + 1], height[i + 1]);
        }
        for (int i = 1; i < height.length - 1; i++) {
            int min = Math.min(maxLeft[i], maxRight[i]);
            if (min > height[i]) {
                sum = sum + (min - height[i]);
            }
        }
        return sum;
    }

总结

  1. 该解法的核心是动态规划预处理:通过递推的方式提前计算每个位置的左右最大高度,避免重复遍历,将时间复杂度优化至O(n);
  2. 接雨水的核心公式是min(左最大高度, 右最大高度) - 当前高度(结果为正才有效),这是所有接雨水解法的底层逻辑;
  3. 该解法空间复杂度为O(n),是时间与空间的平衡选择,若追求极致内存效率,可改用双指针法(无需额外数组),但核心计算逻辑不变。
相关推荐
罗西的思考4 小时前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (4)--- 系统架构
人工智能·算法·机器学习
QiLinkOS4 小时前
从技术到资产的跃迁:企业专利布局的深层逻辑
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
aini_lovee4 小时前
FMCW雷达测速测距系统(锯齿波 + CFAR检测)
算法
qq_297574674 小时前
设计模式系列文章(基础篇第 11 篇):模板方法模式——定义算法骨架,实现代码复用与流程统一
算法·设计模式·模板方法模式
lqqjuly5 小时前
知识蒸馏:理论、算法与可运行实现
人工智能·深度学习·算法
水上冰石5 小时前
comfui的sd1.5模型,有多少采样算法,详解每一个采样算法
人工智能·算法
黎阳之光5 小时前
视频孪生+空天地水工融合,黎阳之光构建智慧水利监测新范式
大数据·人工智能·物联网·算法·安全
cheems95275 小时前
[算法手记] 贪心 爬楼梯问题
算法·贪心算法
KaMeidebaby5 小时前
卡梅德生物技术快报|酵母双杂交 cDNA 文库构建与蛋白互作筛选流程
服务器·前端·数据库·人工智能·算法
圣保罗的大教堂6 小时前
leetcode 3300. 替换为数位和以后的最小元素 简单
leetcode