当前位置: 首页 > news >正文

LeetCode 接雨水问题详解 - 动态规划解法

目录

问题描述

解法思路:动态规划

核心思想

步骤解析

代码实现

复杂度分析

示例解析

画图解析

较矮的墙的高度大于当前列的墙的高度

较矮的墙的高度小于当前列的墙的高度

较矮的墙的高度等于当前列的墙的高度。

总结


问题描述

给定一个非负整数数组 height,每个元素表示柱子的高度。假设这些柱子排列紧密,计算下雨后这些柱子之间能接多少雨水。例如,输入 [0,1,0,2,1,0,1,3,2,1,2,1],输出为 6。

解法思路:动态规划

核心思想

每个位置能接的雨水量取决于其左右两边最高墙中的较矮者。若较矮的墙高于当前柱子,则积水量为两者之差;否则无法积水。

步骤解析

  1. 预处理左右最高墙

    • left[i]:记录位置 i 左边的最高墙(不包含 i)。

    • right[i]:记录位置 i 右边的最高墙(不包含 i)。

  2. 计算积水量:遍历每个位置,取左右最高墙中的较小值,减去当前高度,累加到结果中。

代码实现

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function (height) {
  let n = height.length;
  let left = new Array(n).fill(0); // 左边最高的墙
  let right = new Array(n).fill(0); // 右边最高的墙
  for (let i = 1; i < n; i++) {
    // 从左到右遍历,记录每个位置左边最高的墙
    left[i] = Math.max(left[i - 1], height[i - 1]);
  }
  for (let i = n - 2; i >= 0; i--) {
    // 从右到左遍历,记录每个位置右边最高的墙
    right[i] = Math.max(right[i + 1], height[i + 1]);
  }
  console.log(left, right);
  let ans = 0;
  for (let i = 0; i < n; i++) {
    // 遍历每个位置,计算每个位置能接的水
    let level = Math.min(left[i], right[i]);
    //只有较小的一段大于当前列的高度才会有水,其他情况不会有水
    if (level > height[i]) {
      // 接水 = 较矮的一边减去当前位置的高度
      ans += level - height[i];
    }
  }
  return ans;
};

console.log(trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]));

复杂度分析

  • 时间复杂度:O(n),三次遍历数组。

  • 空间复杂度:O(n),存储左右最高墙的数组。

示例解析

以输入 [0,1,0,2,1,0,1,3,2,1,2,1] 为例:

  1. 预处理左右数组

    • left = [0,0,1,1,2,2,2,2,3,3,3,3]

    • right = [3,3,3,3,3,3,3,2,2,2,1,0]

  2. 计算积水量

    • 对于位置 i=2left[2]=1right[2]=3,较矮者为1。当前高度为0,积水1。

    • 其他位置类似,累加后总积水量为6。

画图解析


求每一列的水,我们只需要关注当前列,以及左边最高的墙,右边最高的墙就够了。

装水的多少,当然根据木桶效应,我们只需要看左边最高的墙和右边最高的墙中较矮的一个就够了。

所以,根据较矮的那个墙和当前列的墙的高度可以分为三种情况。

较矮的墙的高度大于当前列的墙的高度

把正在求的列左边最高的墙和右边最高的墙确定后,然后为了方便理解,我们把无关的墙去掉。

 

这样就很清楚了,现在想象一下,往两边最高的墙之间注水。正在求的列会有多少水?

很明显,较矮的一边,也就是左边的墙的高度,减去当前列的高度就可以了,也就是 2 - 1 = 1,可以存一个单位的水。

较矮的墙的高度小于当前列的墙的高度

同样的,我们把其他无关的列去掉。

 

想象下,往两边最高的墙之间注水。正在求的列会有多少水?

正在求的列不会有水,因为它大于了两边较矮的墙。

较矮的墙的高度等于当前列的墙的高度。

和上一种情况是一样的,不会有水。

明白了这三种情况,程序就很好写了,遍历每一列,然后分别求出这一列两边最高的墙。找出较矮的一端,和当前列的高度比较,结果就是上边的三种情况。

总结

动态规划解法通过预处理左右最高墙,高效计算每个位置的积水量。该方法思路清晰,时间复杂度低,是解决此类问题的经典方法。

http://www.dtcms.com/a/109392.html

相关文章:

  • CentOS 7安装hyperscan
  • LLM驱动的智能体:基于GPT的对话智能体开发指南
  • 如何学习一门编程语言
  • flux绘画模型介绍
  • Java学习总结-字符集
  • 项目之Boost搜索引擎
  • 六种光耦综合对比——《器件手册--光耦》
  • JavaWeb学习--MyBatis-Plus整合SpringBoot的ServiceImpl方法(查找部分)
  • Java在体育比分直播系统搭建中的应用
  • py文件打包为exe可执行文件,涉及mysql连接失败
  • leetcode76.最小覆盖子串
  • podman和与docker的比较 及podman使用
  • Linux红帽:RHCSA认证知识讲解(九)标准输入输出、重定向、过滤器与管道
  • PyTorch的dataloader制作自定义数据集
  • Golang改进后的任务调度系统分析
  • MySQL的进阶语法12(MySQL管理)
  • [250403] HuggingFace 新增检查模型与电脑兼容性的功能 | Firefox 发布137.0 支持标签组
  • 数据库系统-数据库模式
  • UART双向通信实现(序列机)
  • (三十)导入系统内置库 math库
  • 基于大模型预测升主动脉瘤的多维度诊疗研究报告
  • 抖音短视频安卓版流畅度测评 - 真实
  • 关于pycharm远程连接服务器如何debug
  • ngx_log_init
  • RTOS基础 -- NXP M4小核的RPMsg-lite与端点机制回顾
  • Qt基础:主界面窗口类QMainWindow
  • 前端切片上传、上传进度、断点续传、秒传
  • maven项目添加第三方JAR包
  • 《Java编程思想》读书笔记:第九章 接口
  • TI-BQ34Z100 STM32CubeIDE STM32L151 调试过程,含详细步骤文档、代码工程、测试记录、BQ34Z100手册等相关资料