【算法-LeetCode】63. 不同路径 II(动态规划;滚动数组)

2023-11-18

63. 不同路径 II - 力扣(LeetCode)

文章起笔:2021年11月13日16:28:08

问题描述及示例

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?


网格中的障碍物和空位置分别用 1 和 0 来表示。

示例 1:

输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右

示例 2:

输入:obstacleGrid = [[0,1],[0,0]]
输出:1

提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解(动态规划)

有关动态规划的思路总结,之前写过一个相关的题解博客:

参考:【算法-LeetCode】53. 最大子序和(动态规划初体验)_赖念安的博客-CSDN博客

里面也有我写的其他动态规划题解,一些通用的步骤都是一样的,也可以作为参考,进行对照思考。

而本题的思路和我之前做的一个动态规划题目非常像:

参考:【算法-LeetCode】64. 最小路径和(动态规划;二维数组;滚动数组)_赖念安的博客-CSDN博客

两道题目都有共同的特点:dp[i][j] 的值都是由其相邻的正上方元素(dp[i-1][j])和相邻的正左方元素(dp[i][j-1])决定的。所以两者的动态转移方程也有相似之处。

此前我也做过另一道路径问题,可供参考:

参考:【算法-LeetCode】62. 不同路径(动态规划;滚动数组)_赖念安的博客-CSDN博客

本题的思路和上面的思路是一样的,唯一不同的就是本题需要对障碍物做一点判断

我的题解1(二维dp数组)

在本题中,dp[i][j] 代表由起点(也就是点 [0,0])到点 [i][j] 有几条可行的路径(当然,按照题目要求只能向下或想右走)。

具体的分析步骤就不赘述了,和上面那道题的基本一样,只要根据我之前总结的那几个步骤一点点分析即可。说一下本题的总体核心思路:我们要走到点 [i][j] ,只能先到达其正上方或者正左方,所以只要知道到达 [i-1][j][i][j-1] 各有几条符合条件的路径,再将两者相加即可得到到达 [i][j] 总共有几条路径。

但是要注意在遍历过程中对障碍物做一点额外的判断。如果当前遍历的 obstacleGrid元素为障碍物,那么就可以直接将该相应位置的 dp 元素置为 0

而且在本题中,我所创建的 dp 数组的长宽相比较于 obstacleGrid 是增加了一行一列的。这增加的一行一列就相当于是辅助用的行和列,它们的初始值都是 0

详细解释请看下方注释:

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */
var uniquePathsWithObstacles = function(obstacleGrid) {
  // 注意 dp 数组的长宽都比 obstacleGrid 大 1
  let dp = new Array(obstacleGrid.length + 1).fill(0).map(
    // 注意这里我把 dp 数组元素的值都初始化为0,此前我是初始化为1
    () => new Array(obstacleGrid[0].length + 1).fill(0)
  );
  
  //  dp 数组的首行和首列应该被初始化为0,上面创建dp数组的时候就相当于同时完成了初始化
  
  // 开始遍历obstacleGrid数组,同时填充dp数组
  for(let i = 1; i < dp.length; i++) {
    for(let j = 1; j < dp[0].length; j++) {
      // 如果当前遍历的 obstacleGrid 元素为障碍物,则直接让相应的 dp 数组元素为 0
      // 代表到达该位置的路径总条数为 0,注意该判断应当在下面那个判断前以应对[[1]]的情况
      if(obstacleGrid[i-1][j-1] === 1) {
        dp[i][j] = 0;
        continue;
      }
      // 注意要对 dp[1][1] 这个元素做特殊处理
      if(i === 1 && j === 1) {
        dp[i][j] = 1;
        continue;
      }
      // 剩下的元素的填充逻辑就和之前那道题目是一样的了
      dp[i][j] = dp[i][j-1] + dp[i-1][j];
    }
  }
  return dp[dp.length-1][dp[0].length-1];
};


提交记录
执行结果:通过
41 / 41 个通过测试用例
执行用时:88 ms, 在所有 JavaScript 提交中击败了15.78%的用户
内存消耗:38.9 MB, 在所有 JavaScript 提交中击败了31.70%的用户
时间:2021/11/13 16:34	

我的题解2(一维dp数组)

这里用到的“滚动数组”的思路也和上面提到的博客里的思路是一样的,所以就不再赘述了。

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */
var uniquePathsWithObstacles = function(obstacleGrid) {
  // 创建dp数组,注意其长度比obstacleGrid的长度大1,
  // 前面多出来的那个位置(即dp[0])是辅助位,同时dp数组中的元素都被初始化为 0
  let dp = new Array(obstacleGrid[0].length + 1).fill(0);
  // 注意要特意初始化dp[1]这个元素,否则就会影响后续元素的计算
  dp[1] = obstacleGrid[0][0] ? 0 : 1;
  
  // 下面的逻辑没有太大的变化,只不过把原来二维dp数组解法里针对dp[1][1]的操作提到了上面
  for(let i = 0; i < obstacleGrid.length; i++) {
    for(let j = 0; j < obstacleGrid[0].length; j++) {
      if(obstacleGrid[i][j] === 1) {
        dp[j+1] = 0;
        continue;
      }
      dp[j+1] = dp[j+1] + dp[j];
    }
  }
  return dp[dp.length-1];
};


提交记录
执行结果:通过
41 / 41 个通过测试用例
执行用时:72 ms, 在所有 JavaScript 提交中击败了75.27%的用户
内存消耗:38.2 MB, 在所有 JavaScript 提交中击败了87.77%的用户
时间:2021/11/13 17:09	

可以看到,使用一维 dp 数组的时间和空间性能都显著提升了。但是其核心的思路还是不变的,只不过是重复利用了某一个一维数组。而我们可以重复利用这个数组的最关键因素就是:除了需要初始化的那些 dp 元素,其余所有的 dp[i][j] 都是通过其“前面”的元素计算得到的,或者说新的 dp[i][j] 会覆盖前一轮计算得到的 dp[i][j] ,所以一维数组中的某一个位置能够被重复利用。

基本上所有的二维 dp 数组都可以通过上面的思路化为一维数组。所以我觉得在研究一维 dp 数组(滚动数组)前,应该先对二维的实现原理有充分的理解。

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年11月13日16:36:03

参考:不同路径 II - 不同路径 II - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年11月13日16:36:47
参考:【算法-LeetCode】62. 不同路径(动态规划;滚动数组)_赖念安的博客-CSDN博客
更新:2021年9月22日14:08:16
参考:【算法-LeetCode】53. 最大子序和(动态规划初体验)_赖念安的博客-CSDN博客
更新:2021年9月23日22:15:04
参考:【算法-LeetCode】64. 最小路径和(动态规划;二维数组;滚动数组)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】322. 零钱兑换(动态规划;博采众长的完全背包问题详解;二维数组;滚动数组)_赖念安的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法-LeetCode】63. 不同路径 II(动态规划;滚动数组) 的相关文章

  • 跨域XMLHttp请求

    这是我的情况 我有一台 Web 服务器机器 一台客户端机器和第三台运行一些侦听 XMLHttpRequest 的程序的机器 客户端从客户端计算机访问网络服务器 进行一些更改 然后单击 保存 此时 数据被发送回网络服务器和第三台机器 所有这些
  • Jasmine-jQuery loadFixtures 未定义

    我对整个茉莉花的事情仍然很陌生 在过去的几个小时里我陷入了这个问题 我尝试使用 loadFixture 加载外部夹具文件 我使用 Jasmine 2 0 0 和 Jasmine jQuery 2 0 5 ReferenceError loa
  • Angular 2 Material 2 日期选择器日期格式

    我不知道如何更改材料2日期选择器的日期格式 我已阅读文档 但我不明白我实际上需要做什么 datepicker默认提供的输出日期格式为f e 6 9 2017 我想要实现的目标是将格式更改为类似的格式9 Jun 2017或任何其他 文档htt
  • 如何防止 gulp-notify 破坏 Windows 中的 gulp-watch?

    我正在使用吞咽通知 https www npmjs org package gulp notify插入 这是我如何在 gulpfile js 中实现它的示例 您可以看到我也在使用 gutil 和 livereload 我不知道它们是否发挥任
  • window.onbeforeunload 在 Android Chrome 上不会触发 [alt.解决方案?]

    我开发了一个简单的聊天应用程序 我正在使用 window onbeforeunload当有人关闭选项卡 浏览器时 基本上是当用户离开房间时 通知其他用户 这是我的代码 scope onExit function scope chatstat
  • 在鼠标光标位置添加 cytoscape 节点

    我想在画布上的单击事件上的鼠标箭头位置添加一个 cytoscape 节点 我怎样才能做到这一点 我的方法 效果不太好 我可以通过单击创建一个节点 但无法确保创建的节点的位置位于我单击的位置 使用这样的东西 cy click function
  • 以一定时间间隔连续重复运行 JavaScript 函数

    这是我的第一个问题 希望您尽快回答 我想要代码连续重复一个函数 我尝试了一些代码 但没有成功 我尝试了这段代码 我想在一段时间后重复这个功能 我努力了setInterval and setTimeout 但是 我还没有收到结果 这将重复该任
  • Chrome 扩展同步调用 - 仅在窗口关闭后创建窗口

    我有这个代码 function voteNewWindow mailNum chrome windows create url http www google com incognito true function window conso
  • 为什么 length 是 `Array` 的属性而不是 `Array.prototype` 链

    所以我在 V8 控制台上玩了很多 我做到了 Object getOwnPropertyNames 我期望得到 结果 然而 length 所以这意味着不是成为原型链的一部分 length是所有人的成员财产Array对象 这是一个错误 还是有任
  • 启用/禁用由用户输入确定的复选框

    我有一个简单的表单 用户可以在其中输入他的联系号码 如果联系号码以 07 开头 则该复选框已启用 其他我需要禁用它的复选框 我已经编写了一些代码 但我面临的问题是 当用户键入 01 时 它会被禁用 但如果他们继续在 01 之后添加任何其他数
  • 无法实例化模块 [$injector:unpr] 未知提供程序:$routeProvider

    我从 AngularJS 升级时收到此错误1 0 7 to 1 2 0rc1 ngRoute 模块不再是核心的一部分angular js文件 如果您继续使用 routeProvider 那么您现在需要包括angular route js在你
  • 使用 JavaScript 生成 PDF 文件

    我正在尝试将 XML 数据从网页转换为 PDF 文件 并且希望能够完全在 JavaScript 中完成此操作 我需要能够绘制文本 图像和简单的形状 我希望能够完全在浏览器中完成此操作 我刚刚写了一个名为jsPDF https github
  • 通过JS Laravel访问存储目录

    有没有办法访问storage目录 该目录已经链接到publicJS 中的目录 我正在尝试制作一个上传图片的表单 验证脚本 if request gt hasFile photos marker gt photos request gt ph
  • 有没有办法将变量从 javascript 导入到 sass 或反之亦然?

    我正在制作一个依赖于块概念的 CSS 网格系统 所以我有一个基本文件 例如 max columns 4 block width 220px block height 150px block margin 10px 它被 mixin 使用 m
  • 如何从 JSON 响应重定向?

    所以我尝试使用 Flask 和 Javascript 上传器 Dropzone 上传文件并在上传完成后重定向 文件上传正常 但在烧瓶中使用传统的重定向 return redirect http somesite com 不执行任何操作 页面
  • 在 jQuery 可排序中对多个选定项目进行排序?

    我试图在 jQuery 可排序集中选择多个项目 然后将选定的项目一起移动 这是我的弱点开始尝试使其发挥作用 http jsfiddle net benstenson CgD8Y 这是代码 HTML div class container d
  • 了解 JavaScript - 资源

    使用 StackOverflow 的微型 Digit Blog 功能进行描述here https stackoverflow com about 我想发布以下我刚刚看到的 我觉得很有趣的谷歌技术谈话视频 我一直在理解 javascript
  • 为什么 Web Worker 性能在 30 秒后急剧下降?

    我正在尝试提高在网络工作人员中执行时脚本的性能 它旨在解析浏览器中的大型文本文件而不会崩溃 一切都运行得很好 但我注意到使用网络工作者时大文件的性能存在严重差异 于是我做了一个简单的实验 我在同一输入上运行脚本两次 第一次运行在页面的主线程
  • 如何检测元素内容何时发生变化

    我正在寻找一种方法来监视元素内动态填充 无页面重新加载 内容 以便我可以将类添加到另一个元素 到目前为止我有这个 HTML div class message container div class messages error span
  • 在 HTML5 iOS 7 / iOS 8 中显示十进制键盘

    经过几个小时的搜索后 我只是有一个简单的问题 是否有可能在网络浏览器输入字段中显示小数键盘 input type number 只显示数字 但我需要在左下角使用逗号或点 我尝试过任何事情 pattern step等等 但没有显示十进制键盘

随机推荐

  • 每日一练——Python基础(七)

    请设计一个好友管理系统 每个功能都对应一个序号 用户可根据提示 请输入您的选项 选择序号执行相应的操作 包括 1 添加好友 用户根据提示 请输入要添加的好友 输入要添加好友的姓名 添加后会提示 好友添加成功 2 删除好友 用户根据提示 请输
  • Accurate Scale Estimation for Robust Visual Tracking 学习笔记:

    Accurate Scale Estimation for Robust Visual Tracking DSST学习笔记 尺度变化是跟踪中比较基础和常见的问题 目标变小 跟踪器就会吸收大量没有用的背景信息 目标过大 跟踪器就会丢失很多特征
  • HDFS的block和切片(split)的联系和区别

    lt 1 gt 联系 HDFS的block和切片 split 的大小相等 lt 2 gt 区别 1 HDFS存储数据在数据节点上 block是数据节点储存数据的一个个单位 2 split是把block切分而成的虚拟定义 3 split是Ma
  • 华为机试-HJ1 字符串最后一个单词的长度-C语言、python

    刷题第一步 熟悉输入输出及基本套路 前言 题目描述 C语言 题解1 fgets 题解2 scanf 题解3 gets python 题解1 题解2 参考解析 方法一 使用split 直接返回长度 方法二 逐位遍历找空格 前言 本文主要用于个
  • Docker中成功安装修罗Xiunobbs论坛步骤

    组成 php7 mysql5 7 xiunobbs4 04 nginx 1 Pull镜像 docker pull nginx docker pull docker io centos mysql 57 centos7 docker pull
  • Unity动画机制 Animator与Animator Controller教程

    Chinar blog www chinar xin Unity动画机制 Animator Animation 本文提供全流程 中文翻译 Chinar 的初衷是将一种简单的生活方式带给世人 使有限时间 具备无限可能 Chinar 心分享 心
  • SystemC 官方example 代码的静态分析思路与示例 —— 示例项目:TLM at_1_phase

    一 分析TLM2示例的基本流程方法 1 从sc main 开始 发现各个模块类的内部重要模块 以及对外连接的public端口或socket 理清基本has和is关系 2 看顶层类之成员类的构造函数 理清模块类的端口连接关系 socket是稍
  • Jmeter --- time函数生成时间戳

    一 元件位置 Tools 函数助手对话框 二 生成时间戳 1 未作处理的时间戳 2 除以1000 得到少三位数的时间戳
  • Python基本函数:plot()

    Python画图主要用到 matplotlib 库 而具体来说则是matplotlib下的 pylab 和 pyplot 这两个子库 这两个库可以满足基本的画图需求 下面我们只讨论 pyplot库 具体参数可以参看 官方文档 1 plt p
  • for循环python爬虫_轻松领悟for循环,做一款Python版手账

    https www xin3721 com eschool pythonxin3721 Hello 小数先生粗线啦 今天教大家制作一款Pyhon版手账 先看下手账效果 文中最后有手账代码 Python手账 for in 循环语句 for循环
  • 2-2.vue的实例属性:data

    2 2 vue的实例属性 data data属性的作用 data属性的作用是存储vue实例或组件里面的数值 在vue的实例中它是以一个对象的方式 多个键值对 在组件中它是一个函数 通过函数返回一个对象 data在vue的实例里面使用 1 代
  • 锻炼思维小题目

    第一章 假设法 一个真实的假设往往可以让事实呈现眼前 让真理浮出水面 一个人如果做什么事都可以让其思维以这些假设前提为基础 那么他便能真真正正地活在NLP里而不会陷入困境 他的人生也就会有更大地进步和提升 初级题 1 如何问问题 有甲 乙两
  • 人工智能深度学习Caffe框架介绍,优秀的深度学习架构

    人工智能深度学习Caffe框架介绍 优秀的深度学习架构 在深度学习领域 Caffe框架是人们无法绕过的一座山 这不仅是因为它无论在结构 性能上 还是在代码质量上 都称得上一款十分出色的开源框架 更重要的是 它将深度学习的每一个细节都原原本本
  • 什么是DMA

    什么是DMA 当我们向计算机中加入了一块新的声卡或其它适配卡时 安装程序可能会提醒我们应该选择一个DMA通道 那DMA是什么呢 DMA Direct Memory Access 即直接存储器存取 是一种快速传送数据的机制 数据传递可以从适配
  • const类对象的用法

    寻找了一下网上const类对象的用法 因为之前做oj题目的时候一直报错 Problem D 平面上的点 Point类 VI Time Limit 1 Sec Memory Limit 4 MB Submit 5109 Solved 2254
  • 170810 Python-封装RouterScan的DLL

    1625 5 王子昂 总结 2017年8月10日 连续第312天总结 A RouterScan Python封装 B 在老师的指导下验证了ScanRouter的参数应该是结构体的指针 而不是句柄 那么封装可以通过构造一个相同的结构体传入来完
  • PageHelper+BootStrap+Vue+axios实现分页功能

    PageHelper BootStrap Vue axios实现分页功能 效果展示 技术栈 前端技术 Vue2 5 16 axios BootStrap3 3 7 后端技术 SpringBoot2 7 9 MyBatisPlus3 5 1
  • 数据库的导入

    1 进入到数据库 mysql uroot proot 2 创建数据库 create databases wms 3 进入到指定的数据库 use wms 4 设置数据格式 set names utf8 5 导入数据 source data m
  • Linux查看mysql数据库所在目录

    SQL语句 show global variables like datadir 如图所示 有什么不对的还望指正 书写不易 觉得有帮助就点个赞吧
  • 【算法-LeetCode】63. 不同路径 II(动态规划;滚动数组)

    63 不同路径 II 力扣 LeetCode 文章起笔 2021年11月13日16 28 08 问题描述及示例 一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 Start 机器人每次只能向下或者向右移动一步 机器人试图达