【面试经典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.rhkb.cn/news/297105.html

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

相关文章

nut-ui中的menu 菜单组件的二次封装

这个菜单组件 一般可以直接用到项目里 如果复用性不强的话 直接使用 但是有一个问题 如果很多地方都需要用到这个组件 我们可以把这个组件二次封装一下 <template><div class"cinema-search-filter-component"><nut-menu><template #icon>&…

通讯录项目实现

引言&#xff1a;通过顺序表的逻辑实现通讯录。这里就不讲关于顺序表的函数了。如果有不明白的可以看我写的顺序表的博客。 目录 顺序表与通讯录的比较 各源文件文件大榄 Contact.c中通讯录相关函数的定义 初始化和销毁通讯录 添加联系人&#xff1a; 删除联系人&#xf…

Spring的BeanFactory和FactoryBean有什么区别?

两者的区别 BeanFactory定义了ioc容器的最基本形式,并提供了ioc容器应遵守的的最基本的接口,也就是Spring ioc所遵守的最底层和最基本的编程规范,它只是个接口,并不是ioc容器的具体实现。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。再来说说…

UE4_X光效果设置_法线图影响透明度

UE4_X光效果设置_法线图影响透明度 2019-03-22 13:37 Exponentin 设置轮廓光扩散度 baseReflectFactionIn 设置内部黑色的亮度值。nromal&#xff0c;连接应用一张法线图&#xff0c;Lerp两色插值&#xff0c;给两个数值&#xff0c;制造一个渐变。 法线图影响透明度&#xf…

Python实现BOA蝴蝶优化算法优化卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蝴蝶优化算法(butterfly optimization algorithm, BOA)是Arora 等人于2019年提出的一种元启发式智能算…

电商系列之促销

> 插&#xff1a;AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

C/C++程序的(编译,链接)翻译与运行

目录 前言&#xff1a; 1.程序环境 2.翻译环境 3.预处理&#xff08;预编译&#xff09; 4.编译 5.汇编 6.链接 7.运行环境 总结&#xff1a; 前言&#xff1a; 本篇来解释c/c程序的翻译环境与运行环境中的过程&#xff0c;不同的编程语言的翻译环境类似&#xff0c;…

YOLOv8改进 | 低照度检测 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

一、本文介绍 本文给大家带来的2024.3月份最新改进机制,由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络,CPA-Enhancer通过引入链式思考提示机制,实现了对未知退化条件下…

java框架学习——注解/元注解概述及使用案例

前言&#xff1a; 整理下学习笔记&#xff0c;打好基础&#xff0c;daydayup!!! 注解 注解&#xff08;Annotation&#xff09;是java代码里的特殊标记。作用为&#xff1a;让其他程序根据注解信息来决定怎么执行该程序&#xff0c;如&#xff1a;Override,Test等。同时可以根…

956: 约瑟夫问题的实现

【学习版】 【C语言】 #include <iostream> #include <string> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; typedef struct Lnode {int date;struct Lnode* next; }Lnode, * Linklist; int In(Linklist&…

云原生:应用敏捷,华为视角下的应用现代化

Gartner 也提出&#xff0c;到 2023 年&#xff0c;新应用新服务的数量将达到 5 亿&#xff0c;也即是说&#xff1a;“每个企业都正在成为软件企业”。据IDC 预测&#xff0c;到 2025 年三分之二的企业将成为多产的“软件企业”&#xff0c;每天都会发布软件版本。越来越多的企…

尚硅谷50道Java面试题笔记 写的不全

b站链接&#xff1a;https://www.bilibili.com/video/BV1Bb411d7SL/?p4&vd_source714a8042f058b82c668750a0930ff9b0 1 mysql使用innodb引擎&#xff0c;请简述mysql索引的最左前缀如何优化orderby语句。 关键点&#xff1a; 如果排序字段不在索引列上&#xff0c;file…

Vue.js---------Vue基础

能够说出Vue的概念和作用能够使用vue/cli脚手架工程化开发能够熟练Vue指令 一.vue基本概念 1.学习vue Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 渐进…

SpringCloud学习(6)-Micrometer+ZipKin分布式链路追踪

为什么会出现这个技术&#xff1f; 微服务架构中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会…

Linux网络基础(一)网络基础探索之旅

⭐小白苦学IT的博客主页 ⭐初学者必看&#xff1a;Linux操作系统入门 ⭐代码仓库&#xff1a;Linux代码仓库 ❤关注我一起讨论和学习Linux系统 本节重点 了解网络发展背景, 对局域网/广域网的概念有基本认识;了解网络协议的意义, 重点理解TCP/IP五层结构模型;学习网络传输的基本…

docker安装elasticsearch

安装之前需要创建网络 为啥需要创建网络? 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联 创建网络: docker network create es-kibana es-kibana:网络名称,自定义即可 拉取elasticsearch镜像使用7.12.1版本: docker pull elasticsearch7.12.1 …

修改element-ui table组件展开/收起图标、支持点击行展开/收起、隐藏不可展开行得图标

Element中table默认支持的&#xff0c;展开和收起功能&#xff0c;如下&#xff1a; 针对表格的展开收起&#xff0c;本文改造的主要有3点&#xff1a; 1、修改展开/收起的图标&#xff1b; 2、对于不支持展开/收起的行&#xff0c;隐藏图标&#xff1b; 3、点击行&#xff0…

leetcode代码记录(打家劫舍 II

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 一个专业的小偷&#xff0c;计划偷窃一个环形街道上沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是…

Linux驱动学习:从Linux主机nfs共享文件到uboot

第一步&#xff1a;在Linux主机上开启NFS服务&#xff0c;使用如下命令安装NFS服务&#xff1a; sudo apt-get install nfs-kernel-server rpcbind 第二步&#xff1a;创建一个文件夹用于共享&#xff0c;直接以nfs命名就行&#xff1a; 第三步&#xff1a;打开nfs服务配置文…

ES6展开运算符

1.展开可迭代对象&#xff08;简单理解为数组和伪数组&#xff09;&#xff0c;如数组、 NodeList 、arguments。 可以通过展开运算符把一个伪数组转换为数组 const a [...document.body.children]; console.log(a); console.log(Array.isArray(a));2.实现数组的浅拷贝 cons…