leetCode 63.不同路径II 动态规划 + 空间复杂度优化 一维dp

news2024/12/27 12:39:37

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

一个机器人位于一个 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

>>思路

相比这道leetCode 62.不同路径就有了障碍~,其实在有障碍的时候,就是标记对应的dp数组 保持初始值(0)即可!!!

>>动规五部曲

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];
  • 在是障碍的时候,那么(i,j)就保持初始状态(初始状态为0)
if(obstacleGrid[i][j] == 0) { // 当(i,j)没有障碍的时候,再推导dp[i][j]
    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}

3.dp数组初始化

vector<vector<int>> dp(m,vector<int>(n,0));//初始值为0
for(int i = 0;i < m;i++) dp[i][0] = 1;
for(int j = 0;j < n;j++) dp[0][j] = 1;
  • 因为从(0,0)的位置到(i,0)的路径一条,即dp[i][0]一定为1;
  • 因为从(0,0)的位置到(0,j)的路径一条,即dp[0][j]一定为1;

但如果(i,0)这条边有了障碍之后,障碍之后(包括障碍)都是走不到的位置,那障碍之后的dp[i][0]就应是初始值0 

vector<vector<int>> dp(m,vector<int>(n,0));//初始值为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循环的终止条件:

  • ① 遇到obstacleGrid[i][0] == 1终止dp[i][0]的赋值1的操作
  • ② 遇到obstacleGrid[0][j] == 1终止dp[0][j]的赋值1的操作

4.确定遍历顺序

从递推公式dp[i][j] = dp[i-1][j] + dp[i][j-1] 中可以看出,一定是从左到右一层一层遍历,可以保证推导dp[i][j]的时候,dp[i-1][j] 和 dp[i][j-1]一定是有数值的

for(int i = 1;i < m;i++) {
    for(int j = 1;j < n;j++) {
        if(obstacleGrid[i][j]  == 1) continue;
        dp[i][j] = dp[i-1][j] + dp[i][j-1];
    }
}

5.举例推导dp数组

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        if(obstacleGrid[m-1][n-1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0
            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] == 1) continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

// 时间复杂度:O(m x n) m、n分别为 obstacleGrid 的宽度和长度
// 空间复杂度:O(m x n)
  • 时间复杂度:O(m x n) m、n分别为 obstacleGrid 的宽度和长度
  • 空间复杂度:O(m x n)

进一步空间优化:

class Solution {
public:

    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid[0][0] == 1) return 0;
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<int> dp(n);
        for(int j = 0;j < n;j++) {
            if(obstacleGrid[0][j] == 1)
                dp[j] = 0;
            else if(j == 0)
                dp[j] = 1;
            else
                dp[j] = dp[j-1];
        }
        for(int i = 1;i < m;++i) {
            for(int j = 0;j < n;++j) {
                if(obstacleGrid[i][j] == 1) dp[j] = 0;
                else if(j!=0) 
                    dp[j] = dp[j] + dp[j-1];
            }
        }
        return dp.back();
    }
    // 时间复杂度:O(m x n) m、n分别为 obstacleGrid 的宽度和长度
    // 空间复杂度:O(n)
};
  • 时间复杂度:O(m x n) m、n分别为 obstacleGrid 的宽度和长度
  • 空间复杂度:O(n) 

来自代码随想录的课堂截图:

参考和推荐文章、视频:

动态规划,这次遇到障碍了| LeetCode:63. 不同路径 II_哔哩哔哩_bilibili

 代码随想录 (programmercarl.com)

我的往期文章: leetCode 62.不同路径 动态规划 + 空间复杂度优化_呵呵哒( ̄▽ ̄)"的博客-CSDN博客

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

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

相关文章

.NET Core nuget 组件的安装、更新、卸载

上面的 NuGet\ 是可以省略的。 更新 Update-Package xxx 卸载 Uninstall-Package xxx Uninstall-Package Newtonsoft.Json

400G QSFP-DD FR4 与 400G QSFP-DD FR8光模块:哪个更适合您的网络需求?

QSFP-DD 光模块随着光通信市场规模的不断增长已成为400G市场中客户需求量最高的产品。其中400G QSFP-DD FR4和400G QSFP-DD FR8光模块都是针对波分中距离传输&#xff08;2km&#xff09;的解决方案&#xff0c;它们之间有什么不同&#xff1f;应该如何选择应用&#xff1f;飞速…

SpringBoot 学习(二)配置

2. SpringBoot 配置 2.1 配置文件类型 配置文件用于修改 SpringBoot 的默认配置。 2.1.1 properties 文件 **properties ** 是属性文件后缀。 文件名&#xff1a;application.properties 只能保存键值对。 基础语法&#xff1a;keyvalue namewhy注入配置类 Component //…

Java基于SpringBoot的民宿管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 开发环境&#xff1a;后端&#xff1a;前端&#xff1a;数据库&#xff1a; 系统架构&#xff1a…

Vue computed计算属性购物车实例

效果演示 对于computed的计算属性可以通过这个购物车例子来了解&#xff0c;笔者最近很是疲累&#xff0c;真的不想过多解释了&#xff0c;还请读者自行看代码研究。 参考代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"U…

数据库管理-第107期 Relocating PDB(20230927)

数据库管理-第107期 Relocating PDB&#xff08;20230927&#xff09; 在我长期的blog生涯&#xff0c;当需要迁移PDB的时候&#xff0c;出现了几种方式&#xff0c;基本上就是在线克隆或者datapump&#xff0c;然而这两种方式都需要一定的停机时间。在数据库版本一致的情况下…

Redis 数据类型底层原理

String 内部编码有三种&#xff1a;int、embstr、raw int&#xff1a;如果一个字符串对象保存的是整数值&#xff0c;并且这个整数值可以用 long类型来表示(不超过 long 的表示范围&#xff0c;如果超过了 long 的表示范围&#xff0c;那么按照存储字符串的编码来存储&#xf…

notepad++配置python2环境

&#xff08;1&#xff09;python2版本下载&#xff1a;Index of /ftp/python/2.7.8/https://www.python.org/ftp/python/2.7.8/ &#xff08;2&#xff09; 配置notepad环境 1.打开Notepad&#xff0c;点击“插件”-“插件管理器”&#xff0c;在“可用”选项卡中&#xff0c…

使用Process Monitor工具探测日志文件是程序哪个模块生成的

目录 1、问题描述 2、使用Process Monitor监测目标文件是哪个模块生成的思路说明 3、操作Process Monitor监测日志文件是哪个模块生成的 4、通过screenctach.dll库的时间戳&#xff0c;找到其pdb文件&#xff0c;然后去查看详细的函数调用堆栈 5、最后 VC常用功能开发汇总…

C++编程入门与提高:学习策略与技巧

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 摘要&#xff1a;C是一门…

淘宝商品sku信息抓取接口api

在电商行业中&#xff0c;SKU是一个经常被使用的术语&#xff0c;但是对于很多人来说&#xff0c;这个词可能还比较陌生。在这篇文章中&#xff0c;我们将详细解释什么是SKU&#xff0c;以及在电商业务中它的作用和意义。 什么是SKU&#xff1f; SKU是“Stock Keeping Unit”…

Ubuntu 20.04编译GPMP2过程记录

前言 GPMP2是董靖博士等人在16-17年提出的结合GTSAM因子图框架与Gaussian Processes完成motion planning的一项工作。前身源于Barfoot教授的课题组提出的STEAM(Simultaneous Trajectory Estimation and Mapping)问题及其相关工作。在提出董靖博士提出GPMP2后&#xff0c;borgl…

1400*B. Two Buttons(BFS)

解析&#xff1a; 每次一个点有两种情况&#xff0c;-1 和 *2 两种情况&#xff0c;直接 BFS 即可。 #include<bits/stdc.h> using namespace std; const int N2e55; int n,m,vis[N],cnt[N]; void bfs(){queue<int>q;vis[n]1;q.push(n);while(q.size()){auto tq.f…

使用低代码实现一个表单页面 ------ XinBuilder

平台介绍 如果你不是一个前端开发&#xff0c;但是想要实现出一个前端页面。 那么就可以通过低代码的方式&#xff0c;拖拽和配置出你想要的页面。 而XinBuilder就是简单的一套低代码平台&#xff0c;你可以在上面拖拽出自己想要使用的组件并进行配置。使用方式也很简单。 这…

13. ShardingSphere-Proxy 数据库代理

Spring Cloud 微服务系列文章&#xff0c;点击上方合集↑ 1. 简介 ShardingSphere-Proxy是ShardingSphere分布式数据库中间件的一部分&#xff0c;它提供了数据库代理功能。通过引入ShardingSphere-Proxy&#xff0c;可以在无需改动应用程序代码的情况下&#xff0c;实现分库…

什么是商业智能(BI),就看这篇文章足够了

01、什么是商业智能BI&#xff1f; 商业智能BI - 派可数据商业智能BI可视化分析平台 首先要了解什么是商业智能BI&#xff08; Business Intelligence &#xff09;&#xff1f;百度商业智能BI有很多很多官方的定义&#xff0c;各种解释&#xff0c;实际上从这么多年的经验出发…

AI 大模型

随着人工智能技术的迅猛发展&#xff0c;AI 大模型逐渐成为推动人工智能领域提升的关键因素&#xff0c;大模型已成为了引领技术浪潮研究和应用方向。大模型即大规模预训练模型&#xff0c;通常是指那些在大规模数据上进行了预训练的具有庞大规模和复杂结构的人工智能模型&…

【2023款奔驰改款E260 L运动型:豪华与性能的完美结合】

在汽车市场中&#xff0c;奔驰一直以其卓越的品质和卓越的性能赢得了消费者的喜爱。而2023款奔驰改款E260 L运动型&#xff0c;更是将豪华与性能完美结合&#xff0c;让人无法抗拒。首先&#xff0c;让我们来看一下这款车的外观设计。新款E260 L运动型的前脸设计更加犀利&#…

css 语法笔记

.abc {margin-left:20px; } .xyz {margin-left:20px; } 等同于 .abc, .xyz {margin-left: 20px; } 参考 CSS - 选择器_css最后一个元素选择器_伏城之外的博客-CSDN博客 CSS Selectors Reference

ElasticSearch - 基于 DSL 、JavaRestClient 实现数据聚合

目录 一、数据聚合 1.1、基本概念 1.1.1、聚合分类 1.1.2、特点 1.2、DSL 实现 Bucket 聚合 1.2.1、Bucket 聚合基础语法 1.2.2、Bucket 聚合结果排序 1.2.3、Bucket 聚合限定范围 1.3、DSL 实现 Metrics 聚合 1.4、基于 JavaRestClient 实现聚合 1.4.1、组装请求 1…