LeetCode刷题复盘笔记—一文搞懂62. 不同路径 63. 不同路径 II(动态规划系列第三篇)

news2025/1/12 3:52:29

今日主要总结一下动态规划的两道题目,62. 不同路径 && 63. 不同路径 II

题目一:62. 不同路径

题目描述:
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

在这里插入图片描述

输入:m = 3, n = 7
输出:28
示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。

  1. 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右
  3. 向下 -> 向右 -> 向下
    示例 3:

输入:m = 7, n = 3
输出:28
示例 4:

输入:m = 3, n = 3
输出:6

提示:

1 <= m, n <= 100
题目数据保证答案小于等于 2 * 109

本题重难点

这道题目,刚一看最直观的想法就是用图论里的深搜,来枚举出来有多少种路径。

注意题目中说机器人每次只能向下或者向右移动一步,那么其实机器人走过的路径可以抽象为一棵二叉树,而叶子节点就是终点!

如图举例:

62.不同路径
此时问题就可以转化为求二叉树叶子节点的个数
大家如果提交了代码就会发现超时了!
来分析一下时间复杂度,这个深搜的算法,其实就是要遍历整个二叉树。
这棵树的深度其实就是m+n-1(深度按从1开始计算)。
那二叉树的节点个数就是 2^(m + n - 1) - 1。可以理解深搜的算法就是遍历了整个满二叉树(其实没有遍历整个满二叉树,只是近似而已)
所以上面深搜代码的时间复杂度为O(2^(m + n - 1) - 1),可以看出,这是指数级别的时间复杂度,是非常大的。

所以深搜不行,考虑动态规划来试一下:
如前面系列文章一文搞懂动态规划系列(第一篇)509. 斐波那契数70. 爬楼梯和一文搞懂746. 使用最小花费爬楼梯所讲:
对于动态规划问题,可以拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。

按照动规五部曲来分析:

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  2. 确定递推公式
    想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。
    此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。
    那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。

  3. dp数组的初始化
    如何初始化呢,首先dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。

  4. 确定遍历顺序
    这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。
    这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。

  5. 举例推导dp数组

如图所示:
在这里插入图片描述

C++代码

方法一、常规动态规划

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for(int i = 0; i < m; i++) dp[i][0] = 1;
        for(int j = 0; j < n; j++) dp[0][j] = 1;
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

时间复杂度:O(n)
空间复杂度:O(n)

方法二、动归空间复杂度优化
其实用一个一维数组(也可以理解是滚动数组)就可以了,但是不利于理解,可以优化点空间,建议先理解了二维,在理解一维,C++代码如下:

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<int> dp(n);
        for (int i = 0; i < n; i++) dp[i] = 1;
        for (int j = 1; j < m; j++) {
            for (int i = 1; i < n; i++) {
                dp[i] += dp[i - 1];
            }
        }
        return dp[n - 1];
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

题目二:63. 不同路径 II

题目描述:
一个机器人位于一个 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

本题重难点

这道题相对于上一题62.不同路径就是有了障碍。

第一次接触这种题目的同学可能会有点懵,这有障碍了,应该怎么算呢?

62.不同路径中我们已经详细分析了没有障碍的情况,有障碍的话,其实就是标记对应的dp table(dp数组)保持初始值(0)就可以了

机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。

按照动规五部曲来分析:

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  2. 确定递推公式
    递推公式和62.不同路径一样,dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。
    但这里需要注意一点,因为有了障碍,(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0)。

  3. dp数组的初始化
    但如果(i, 0) 这条边有了障碍之后,障碍之后(包括障碍)都是走不到的位置了,所以障碍之后的dp[i][0]应该还是初始值0。

如图:
在这里插入图片描述
一旦遇到obstacleGrid[i][0] == 1的情况就停止dp[i][0]的赋值1的操作,dp[0][j]同理

  1. 确定遍历顺序
    这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。
    这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。

  2. 举例推导dp数组

C++代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        if(obstacleGrid[0][0] || obstacleGrid[m -1][n - 1]) return 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for(int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
        for(int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                if(obstacleGrid[i][j] == 0){
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
};

时间复杂度:O(n)
空间复杂度:O(n)

可以看出来,加了障碍物的不同路径二相比于第一题,最大的不同主要体现在动规五步曲里面的递推公式更新条件判断上和dp数组初始化上面!


总结

动态规划
英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。
动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的

对于动态规划问题,可以拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

这篇文章主要总结了一些动态规划解决不含和包含障碍物的不同路径的两道题目,依然是使用动规五部曲,加了障碍物的不同路径二相比于第一题,最大的不同主要体现在动规五步曲里面的递推公式更新条件判断上和dp数组初始化上面!

做每道动态规划题目这五步都要弄清楚才能更清楚的理解题目!


欢迎大家关注本人公众号:编程复盘与思考随笔

(关注后可以免费获得本人在csdn发布的资源源码)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/19702.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML CSS 网页设计作业「体育小站」(梅西足球 6页 )

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 校园篮球网页设计 | 足球体育运动 | 体育游泳运动 | 兵乓球 | 网球 | 等网站的设计与制作| HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HT…

JavaScript之PC端网页特效(55th)

在前面学习了JS基础、DOM 和 BOM 的基本操作后&#xff0c;这部分主要学习这些知识的拓展应用 1、元素偏移量 offset 系列 1、offset 概述 offset 翻译过来就是偏移量&#xff0c;我们使用 offset 系列相关属性可以动态的得到该元素的位置&#xff08;偏移&#xff09;、大小…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.7 SpringBoot 操作 Redis 客户端实现技术切换【jedis】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.7 SpringBoot 操作 Redis 客户端实现技术切换【je…

数据结构实验教程-第二套

5.一棵左子树为空的二叉树在先序线索化后&#xff0c;其中空的链域的个数是 a&#xff0e;不确定 b.0 c.1 d.2在先序线索化之后&#xff0c;相当于只有开始节点没有前驱&#xff0c;最后的节点没有后继&#xff0c;因此空链域只有2个&#xff0c;分别是开始节点的左孩子和最后节…

【笔试题】【day23】

文章目录第一题&#xff08;二叉树度结点的计算&#xff09;第二题&#xff08;平衡查找二叉树&#xff09;第三题&#xff08;堆的插入&#xff09;第四题&#xff08;哈希表的查找&#xff09;第五题&#xff08;大数排序&#xff09;第一题&#xff08;二叉树度结点的计算&a…

功能测试

功能测试 按照是否覆盖源代码 黑盒测试&#xff08;输入和输出&#xff09; 白盒测试&#xff08;代码内部实现逻辑&#xff09; 灰盒测试&#xff08;输入输出和代码逻辑&#xff09; 介于白盒测试和黑盒测试之间的测试&#xff0c;多用于集成阶段&#xff0c;不仅关注输入输…

智能制造与数字化工厂

智能制造是基于新一代信息技术&#xff0c;贯穿设计、生产、管理、服务等制造活动各个环节&#xff0c;具有信息深度自感知、智慧优化自决策、精准控制自执行等功能的先进制造过程、系统与模式的总称。具有以智能工厂为载体&#xff0c;以关键制造环节智能化为核心&#xff0c;…

通信用多模光纤主要有哪些类型?OM1~OM5有什么区别

1 前言 根据光纤内光信号传输模式的不同&#xff0c;光纤可分为单模光纤和多模光纤&#xff0c;见《常用通信光纤是如何分类的》一文。 在传送网和有线接入网中&#xff0c;我们接触到的光纤类型主要有&#xff1a;G.652、G.654和G.657&#xff0c;这些都是单模光纤。多模光纤…

Linux 系统启动过程

linux启动时我们会看到许多启动信息。 Linux系统的启动过程并不是大家想象中的那么复杂&#xff0c;其过程可以分为5个阶段&#xff1a; 内核的引导。运行 init。系统初始化。建立终端 。用户登录系统。init程序的类型&#xff1a; SysV: init, CentOS 5之前, 配置文件&#…

通关算法题之 ⌈二叉树⌋ 上

二叉树深度 104、求二叉树最大深度 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数&#xff0c;叶子节点是指没有子节点的节点。 示例&#xff1a; 给定二叉树[3,9,20,null,null,15,7]&#xff0c; 3/ \9 20/ \15 7返回它的最大深度 3。 解法一&#xff1a;递…

Linux进阶-Shell编程

目录 定义变量&#xff1a; 使用变量&#xff1a; 将命令的结果赋值给变量&#xff1a; 删除变量&#xff1a;unset 退出当前进程&#xff1a;exit 读取从键盘输入的数据 &#xff1a;read 对整数进行数字运算&#xff1a;(()) 逻辑与或&#xff1a; 检测某个条件是否成…

Qt QSqlQueryModel详解

1.功能概述 QSqlQueryModel是QSqlTableModel的父类。QSqlQueryModel封装了执行SELECT语句从数据库查询数据的功能&#xff0c;但是QSqlQueryModel只能作为只读数据源使用&#xff0c;不可以编辑数据。 2.常用API void clear() //清除数据模型&#xff0c;释放所有获得的数据…

投资有风险,入市需谨慎

投资有风险&#xff0c;入市需谨慎投资有风险&#xff0c;入市需谨慎股票的分类股票的分时图股票K线图股票交易规则股票趋势股票买卖机制投资有风险&#xff0c;入市需谨慎 感谢平台和大家支持&#xff0c;今天不聊技术&#xff0c;了解了解其他方面&#xff0c;比如股市&…

编程思维是一种什么思维?

hello wordl&#xff01;    keep coding&#xff01;&#x1f3c3; 学编程不是将来要当程序猿&#xff0c;而是在学习编程思维。比尔盖茨、扎克伯格、乔布斯用经验告诉我们&#xff0c;拥有编程思维的人&#xff0c;就相当于成功了一半——不但逻辑清晰心思缜密&#xff0c;…

vue + el-checkbox 单选功能

需求: 用 el-checkboc 实现单选功能并且当选中某一项时则回填到input框里,当点击 enter 键或者是 按下搜索图标按键,来实现页面搜索内容的同步展示;如图: <el-checkbox-group placeholder"请选择"size"small"v-model"checkedCols"clearablefi…

Android BLE HIDS Data ,从问询DB 到写入Android 节点的flow之二

问题点4&#xff1a;Android BLE具体连接flow 并问询DB的API flow 之第一阶段问询&#xff1b; 当前确认原生BT当作为GATT Client 连接上GATT Server时&#xff0c;在连接上后会有自动启动问询的动作(以下Tracing 基于Android 9(P), 测试 8.1的代码和Android 8.0有差异&#x…

Web大学生网页作业成品——抗击疫情网站设计与实现(HTML+CSS)实训素材

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 击疫情致敬逆行者感人类题材 | 致敬逆行者网页设计作品 | 大学生抗疫感动专题网页设计作业模板 | 等网站的设计与制作 | HTML期末大学生网页设计作业 …

第3阶段-运维线上实战-3.2企业级nginx使用

企业级nginx使用 nginx实现平滑升级 [rootlnmp nginx-1.16.0]# cd /usr/local/nginx/sbin/ [rootlnmp sbin]# ls nginx nginx.old [rootlnmp sbin]# ./nginx -v nginx version: nginx/1.16.0 [rootlnmp sbin]# ./nginx.old -v nginx version: nginx/1.14.2 [rootlnmp sbin]#操…

【Spring】Spring的AspectJ的AOP

Spring学习笔记(10)Spring的AspectJ的AOP 在Spring中使用AspectJ实现AOP AspectJ 是一个面向切面的框架&#xff0c; 它扩展了 Java 语言。 AspectJ 定义了 AOP 语法所以它有一个专门的编译器用来生成遵守 Java 字节编码规范的 Class 文件。AspectJ 是一个基于 Java 语言的 A…

[附源码]java毕业设计双学位在线考试系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…