【面试经典150 | 动态规划】不同路径 II

文章目录

  • 写在前面
  • Tag
  • 题目1
    • 方法一:动态规划
    • 方法二:空间优化
  • 题目2
    • 方法一:动态规划+空间优化
  • 写在最后

写在前面

本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……

专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:

  • Tag:介绍本题牵涉到的知识点、数据结构;
  • 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
  • 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
  • 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
  • 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。

Tag

【动态规划-空间优化】【网格】


题目1

62. 不同路径


方法一:动态规划

本题是解题思路与 【面试经典150 | 动态规划】最小路径和 类似。

定义状态

定义 f[i][j] 表示机器人从网格左上角 (0, 0) 到位置 (i, j) 可以行走的不同位置数量。

转移关系

根据 “机器人每次只能向下或者向右移动一步”,可知到达 (i, j) 位置可以从 (i-1, j)(i, j-1) 行走到达,于是有转移关系:

f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] f[i][j] = f[i-1][j] + f[i][j-1] f[i][j]=f[i1][j]+f[i][j1]

base case

因为 “机器人每次只能向下或者向右移动一步”,所以机器人从 (0, 0) 位置到第 0 行、第 0 列的不同路径数均为 1。

最后返回

最后返回 f[m-1][n-1],表示机器人从网格左上角 (0, 0) 到网格右下角 (m-1, n-1) 可以行走的不同路径数量。

实现代码

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

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为网格的行数, n n n 为网格的列数。

空间复杂度: O ( m n ) O(mn) O(mn)

方法二:空间优化

仿照 【面试经典150 | 动态规划】最小路径和 中空间优化的思想,可以对朴素的动态规划法进行类似的空间优化。具体实现见代码。

实现代码

class Solution {
public:int uniquePaths(int m, int n) {int more = max(m, n);int less = min(m, n);vector<int> f(less, 1);for (int i = 1; i < more; ++i) {for (int j = 1; j < less; ++j) {/*f[j] = f[j] + f[j-1] 第二个f[j] 表示从上一行向下到达位置(i,j)f[j-1] 表示从上一列向右到达位置(i,j)*/ f[j] += f[j-1];         }}return f[less-1];}
};

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为网格的行数, n n n 为网格的列数。

空间复杂度: O ( m i n { m , n } ) O(min\{m,n\}) O(min{m,n})

题目2

63. 不同路径 II


方法一:动态规划+空间优化

对比上一个题目,本题增加了障碍物,解法上与上题基本一致。但是有几处变动:

  • 遇到障碍物时 f [ i ] [ j ] = 0 f[i][j]=0 f[i][j]=0
  • 本题只需要考虑没有遇到障碍物即 o b s t a c l e G r i d [ i ] [ j ] ! = 1 obstacleGrid[i][j] != 1 obstacleGrid[i][j]!=1 时的不同路径数的问题,此时的状态转移方程也和上题一致。

朴素的动态规划方法

直接给出朴素的动态规划解法。

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size(), n = obstacleGrid[0].size();vector<vector<int>> f(m, vector<int>(n));f[0][0] = obstacleGrid[0][0] == 1 ? 0 : 1;// 初始化第 0 行for(int j = 1; j < n; ++j) {if (obstacleGrid[0][j] != 1) {f[0][j] = f[0][j-1];}}// 初始化第 0 列for (int i = 1; i < m; ++i) {if (obstacleGrid[i][0] != 1) {f[i][0] = f[i-1][0];}}// 计算一般位置for (int i = 1; i < m; ++i) {for(int j = 1; j < n; ++j) {if (obstacleGrid[i][j] != 1) {f[i][j] = f[i-1][j] + f[i][j-1];}}}return f[m-1][n-1];}
};

空间优化

先贴出代码

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size(), n = obstacleGrid[0].size();int more = max(m, n), less = min(m, n);bool rowMore = (more == m);vector<int> f(less);f[0] = (obstacleGrid[0][0] == 0);for (int i = 0; i < more; ++i) {for (int j = 0; j < less; ++j) {if ((rowMore && obstacleGrid[i][j] == 1) || (!rowMore && obstacleGrid[j][i] == 1)) {f[j] = 0;continue;}if ((rowMore && j-1 >= 0 && obstacleGrid[i][j-1] == 0) || (!rowMore && j-1 >= 0 && obstacleGrid[j-1][i] == 0)) {f[j] += f[j-1];}}}return f[less-1];}
};

我们使用布尔变量 rowMore 来表示网格的行数是都大于列数:

  • 如果行数大于等于列数,则有 rowMore =true,此时按行更新 f;如果 (i, j) 位置有障碍物则更新 f[j] = 0;如果前一列的位置没有障碍物,则可以从前一列到达本列,更新 f[j] = f[j] + f[j-1],其中第二个 f[j] 表示上一行的位置 (i-1, j) 的不同路径数。
  • 如果行数小于列数,则有 rowMore =false,此时按列更新 f;如果 (j, i) 位置有障碍物则更新 f[j] = 0;如果前一行的位置没有障碍物,则可以从前一行到达本行更新 f[j] = f[j] + f[j-1],其中第二个 f[j] 表示上一列的位置 (j, i-1) 的不同路径数。
  • 可能会有点绕,读者还需多多阅读体会。如果实现想不明白,可以直接按照行来更新 f,这样空间复杂度为 O ( n ) O(n) O(n)

复杂度分析

时间复杂度: O ( m n ) O(mn) O(mn) m m m 为网格的行数, n n n 为网格的列数。

空间复杂的:经过空间优化后的空间复杂度为 O ( m i n { m , n } ) O(min\{m,n\}) O(min{m,n})。朴素动态规划的时间复杂度为 O ( m n ) O(mn) O(mn)


写在最后

如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。

最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。

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

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

相关文章

启动mysql

删除C:\Program Files (x86)\MySQL\MySQL Server 5.7这个路径下的data文件夹&#xff0c;这个很难删除&#xff0c;因为一开机&#xff0c;mysql的某些服务就启动了&#xff0c;每次重新启动mysql之前&#xff0c;都要删除这个文件夹 因为这个文件夹在后端执行一些我们看不到的…

2024.3.31学习记录————树莓派4B学习一:环境配置

2024.3.31学习记录————树莓派4B学习一&#xff1a;环境配置 准备跳槽&#xff0c;重新选择方向以嵌入式为目标进行学习&#xff0c;因没有硬件基础&#xff0c;先选择了树莓派&#xff0c;准备通过树莓派开发板对驱动初步熟悉后再开始STM32和51单片机开发。 硬件配置 硬…

[技术闲聊]我对电路设计的理解(五)-如何获取datasheet

一、序言 电路设计的前提是明确设计规格&#xff0c;并转化为具体功能&#xff0c;依据功能确定芯片选型范围。 元器件选型的前提是了解每一类芯片的功能&#xff0c;界定该芯片是否合适。 了解的前提是有datasheet文件可以看。 二、获取datasheet的途径有三类 一类&#x…

MySQL-逻辑架构:逻辑架构分析、SQL执行流程、数据库缓冲池

逻辑架构 1. 逻辑架构剖析 1.1 第1层&#xff1a;连接层 系统&#xff08;客户端&#xff09;访问MySQL服务器前&#xff0c;做的第一件事就是建立TCP连接。 经过三次握手建立连接成功后&#xff0c;MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取。 用户名或密码…

numpy 向量的运算法则公式

import numpy as np #构建向量数组 anp.array([-1,2]) bnp.array([3,-1]) #加法 a_bab #数乘 a2a*2 b3b*(-3) #减法 b_aa-b #print(a_b,a2,b3,b_a,a,b)print(-13,2-1,a_b)print(-1-3,2-(-1),b_a)print((-1*2),(2*2),a2)print((3*(-3)),(-1*(-3)),b3) 这段代码主要是使用NumPy库…

C语言------冒泡法排序

一.前情提要 1.介绍 冒泡法排序法&#xff1a; 1)冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;它重复地遍历要排序的列表&#xff0c;一次比较相邻的两个元素&#xff0c;并且如果它们的顺序错误就将它们交换过来。重复这个过程直到没有需…

DeepWalk论文翻译

DeepWalk论文翻译 DeepWalk: Online Learning of Social Representations DeepWalk&#xff1a;社会表征的在线学习 ABSTRACT 我们提出了 DeepWalk&#xff0c;一种学习网络中顶点潜在表示的新方法。这些潜在表示在连续向量空间中对社会关系进行编码&#xff0c;很容易被统…

VRRP虚拟路由器冗余协议

vrrp是为了解决单点故障问题 将几台路由器联合成一台虚拟的路由器&#xff0c;保证通信的可靠性 协议小说&#xff1a; 协议不是在固定的哪一个层&#xff0c;是基于哪一层工作&#xff0c;比如说ospf是基于三层工作的 VRRP是基于三层工作的&#xff0c;就在前面会封装一个ip…

JAVAEE——多线程进阶,锁策略

文章目录 锁策略乐观锁和悲观锁乐观锁悲观锁两者的比较 读写锁重量级锁和轻量级锁重量级锁轻量级锁 自旋锁公平锁和非公平锁公平锁非公平锁 可重入锁和不可重入锁可重入锁不可重入锁 锁策略 乐观锁和悲观锁 乐观锁 什么是乐观锁呢&#xff1f;我们可以认为乐观锁比较自信&am…

网络原理 - HTTP / HTTPS(4)——构造http请求

目录 一、postman 的下载安装以及简单介绍 1、下载安装 2、postman的介绍 二、通过 Java socket 构造 HTTP 请求 构造http请求的方式有两种&#xff1a;&#xff08;1&#xff09;通过代码构造&#xff08;有一点难度&#xff09; &#xff08;2&#xff09;通过第三…

Anaconda/Python快速安装jieba 【win/mac】

一、直接上命令 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba 我是在PyCharm里面的终端输进去。 之后就很快速的看到成功的下图。 二、官网 官网下载的速度太慢了——这是官网地址https://pypi.org/project/jieba/#files 点进去之后点击下载&#xff0c…

【卷积神经网络进展】

打基础日常记录 CNN基础知识1. 感知机2. DNN 深度神经网络&#xff08;全连接神经网络&#xff09;DNN 与感知机的区别DNN特点&#xff0c;全连接神经网络DNN前向传播和反向传播 3. CNN结构【提取特征分类】4. CNN应用于文本 CNN基础知识 1. 感知机 单层感知机就是一个二分类…

Mysql不同条件设置相同的值(使用子查询)

WHEN type1 THEN payable_price WHEN type2 THEN payable_price ELSE MAX(payable_price) type1 表示订单维度&#xff0c;type2表示商品维度&#xff0c;需要无论type值为多少都取type1时的payable_price值 解决方案&#xff1a; 使用SQL子查询; SELECT CASE WHEN type …

利用AI结合无极低码(免费版)快速实现接口开发教程,会sql即可,不需要编写编译代码

无极低码无代码写服务+AI实践 本次演示最简单的单表无代码增删改查发布服务功能,更复杂的多表操作,安全验证,多接口调用,自自动生成接口服务,生成二开代码,生成调用接口测试,一键生成管理界面多条件检索、修改、删除、查看、通用公共接口调用、通用无限级字典调用等后续…

Java的Cookie和Session配合解决会话管理问题

目录 会话管理概述 为什么需要会话管理 会话管理实现的手段 Cookie Cookie概述 Cookie的使用 Cookie的时效性 Cookie的提交路径 Session HttpSession概述 HttpSession的使用 HttpSession时效性 cookie和session结合使用 会话管理概述 为什么需要会话管理 在Java…

【Java入门教程】第二十讲:集合和常见操作

集合框架&#xff08;Collection&#xff09;是 Java 编程语言中一个非常重要的组成部分&#xff0c;它为存储和操作数据提供了一套灵活而强大的API。 本文将详细介绍Java集合框架的基本概念、常用接口和实现类&#xff0c;并通过代码示例来加深理解&#xff0c;帮助大家更好地…

Vue中生成二维码,使用现有的二维码库qrcode

要在Vue中生成二维码&#xff0c;你可以使用现有的二维码库&#xff0c;如qrcode。首先&#xff0c;你需要安装这个库。在你的项目目录下&#xff0c;运行以下命令&#xff1a; bash 复制 npm install qrcode --save 然后&#xff0c;在你的Vue组件中&#xff0c;你可以这样使…

ssm基于jsp的学生作业管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本学生作业管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

C#(C Sharp)学习笔记_Enum枚举类型【十三】

什么是枚举类型 枚举类型(Enum) 是由基础整型数值类型的一组命名常量定义的值类型。枚举包含自己的值&#xff0c;但不能继承或传递继承。 语法 // enum enum_name // enum_name variable enum_name.enum_value// 定义一个枚举类型——例如&#xff1a; enum enum_name {va…

【MATLAB源码-第30期】基于matlab的内边界边缘检测算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 在计算机视觉领域&#xff0c;图像分割&#xff08;segmentation&#xff09;指的是将数字图像细分为多个图像子区域&#xff08;像素的集合&#xff09;&#xff08;也被称作超像素&#xff09;的过程。图像分割的目的是简化…