当前位置: 首页 > news >正文

代码随想录算法训练营第39天 | ● 62.不同路径 ● 63. 不同路径II

文章目录

  • 前言
  • 一、62.不同路径
  • 二、63.不同路径II
  • 总结

前言

动态规划


一、62.不同路径

  • 深搜
  • 动态规划
  • 数论

深搜:

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

如图举例:

62.不同路径

此时问题就可以转化为求二叉树叶子节点的个数,代码如下:

class Solution {
private:int dfs(int i, int j, int m, int n) {if (i > m || j > n) return 0; // 越界了if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点return dfs(i + 1, j, m, n) + dfs(i, j + 1, m, n);}
public:int uniquePaths(int m, int n) {return dfs(1, 1, m, n);}
};

这棵树的深度其实就是m+n-1(深度按从1开始计算)。

那二叉树的节点个数就是 2^(m + n - 1) - 1。可以理解深搜的算法就是遍历了整个满二叉树(其实没有遍历整个满二叉树,只是近似而已)

所以上面深搜代码的时间复杂度为O(2^(m + n - 1) - 1),可以看出,这是指数级别的时间复杂度,是非常大的。


动态规划:

  1. 定dp数组(dp table)以及下标的含义

dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  1. 确定递推公式

想要求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]只有这两个方向过来。

  1. dp数组的初始化

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

所以初始化代码为:

for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
  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]一定是有数值的。

  1. 举例推导dp数组

如图所示:

62.不同路径1

代码:

class Solution {public int uniquePaths(int m, int n) {int dp[][] = new int[m][n];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];}
}


数论:

在这个图中,可以看出一共m,n的话,无论怎么走,走到终点都需要 m + n - 2 步。

62.不同路径

在这m + n - 2 步中,一定有 m - 1 步是要向下走的,不用管什么时候向下走。

那么有几种走法呢? 可以转化为,给你m + n - 2个不同的数,随便取m - 1个数,有几种取法。

那么这就是一个组合问题了。

求组合的时候,要防止两个int相乘溢出! 所以不能把算式的分子都算出来,分母都算出来再做除法。

需要在计算分子的时候,不断除以分母,代码如下:

class Solution {
public:int uniquePaths(int m, int n) {long long numerator = 1; // 分子int denominator = m - 1; // 分母int count = m - 1;int t = m + n - 2;while (count--) {numerator *= (t--);while (denominator != 0 && numerator % denominator == 0) {numerator /= denominator;denominator--;}}return numerator;}
};
  • 时间复杂度:O(m)
  • 空间复杂度:O(1)

计算组合问题的代码还是有难度的,特别是处理溢出的情况!

二、63.不同路径II

动规五部曲:

  1. 确定dp数组(dp table)以及下标的含义

dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  1. 确定递推公式

递推公式和62.不同路径一样,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];
}
  1. dp数组如何初始化

在62.不同路径

(opens new window)不同路径中我们给出如下的初始化:

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,dp[0][j]也同理。

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

如图:

63.不同路径II

下标(0, j)的初始化情况同理。

所以本题初始化代码为:

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循环的终止条件,一旦遇到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 - 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];}
}
  1. 举例推导dp数组

拿示例1来举例如题:

63.不同路径II1

对应的dp table 如图:

63.不同路径II2

class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int m = obstacleGrid.length;int n = obstacleGrid[0].length;int dp[][] = new int[m][n];if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1){return 0;}for(int i = 0;i<m && obstacleGrid[i][0] ==0;i++){dp[i][0] = 1;}for(int i = 0;i<n && obstacleGrid[0][i] ==0;i++){dp[0][i] = 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];}else{dp[i][j] = 0;}}}return dp[m-1][n-1];}
}


总结

今天去看《奥本海默》。

相关文章:

代码随想录算法训练营第39天 | ● 62.不同路径 ● 63. 不同路径II

文章目录 前言一、62.不同路径二、63.不同路径II总结 前言 动态规划 一、62.不同路径 深搜动态规划数论 深搜&#xff1a; 注意题目中说机器人每次只能向下或者向右移动一步&#xff0c;那么其实机器人走过的路径可以抽象为一棵二叉树&#xff0c;而叶子节点就是终点&#…...

《网站建设:从规划到发布的全过程详解》

一、引言 在数字时代&#xff0c;网站已经成为企业和个人在互联网上的重要存在。一个优质网站的建立需要周全的规划、设计、开发、测试和发布。本文将详细介绍网站建设的全过程&#xff0c;帮助读者了解和掌握网站建设的流程和方法。 二、网站建设的意义 网站建设具有以下意…...

1分钟实现 CLIP + Annoy + Gradio 文搜图+图搜图 系统

多模态图文搜索系统 CLIP 进行 Text 和 Image 的语义EmbeddingAnnoy 向量数据库实现树状结构索引来加速最近邻搜索Gradio 轻量级的机器学习 Web 前端搭建 文搜图 图搜图 CLIP图像语义提取功能&#xff01;...

用树形dp+状压维护树上操作的计数问题:0902T3

发现操作数 k ≤ 6 k\le6 k≤6&#xff0c;可以考虑对操作进行状压。 然后找找性质&#xff0c;发现要么删掉一棵子树&#xff0c;要么进去该子树。可以视为每种操作有两种情况。 然后分讨一下当前该如何转移。 树形dp的顺序&#xff1a; 合并子树考虑当前往上的边的方向 …...

【python爬虫】批量识别pdf中的英文,自动翻译成中文上

不管是上学还是上班,有时不可避免需要看英文文章,特别是在写毕业论文的时候。比较头疼的是把专业性很强的英文pdf文章翻译成中文。我记得我上学的时候,是一段一段复制,或者碰到不认识的单词就百度翻译一下,非常耗费时间。本文提供批量识别pdf中英文的方法,后续文章实现自…...

Android笔记--Hilt

Hilt 是 Android 的依赖项注入库&#xff0c;可减少在项目中执行手动依赖项注入的样板代码。执行手动依赖项注入要求您手动构造每个类及其依赖项&#xff0c;并借助容器重复使用和管理依赖项。依赖注入的英文是Dependency Injection&#xff0c;简称DI,简单说一个类中使用的依赖…...

Oracle常用权限处理

对于Oracle来说&#xff0c;用户等于Schema&#xff0c;创建用户即创建Schema -- 创建用户 create user TCK_TEXT identified by "TCKTCK"; --赋予登陆权限 grant connect to TCK_TEXT; --查看权限列表 select * from user_role_privs ; select * from user_sys_priv…...

Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作

Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作 目录 Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作 一、简单介绍 二、汉化操作 附录&#xff1a; 一、Install from URL 中出现 Failed to connect to 127.0.0.1 port 7890: Connection refused 错误&#xf…...

r 安装源码包 安装本地r包

总结一下手动安装R包 - 简书 (jianshu.com)https://www.jianshu.com/p/2a7a36414734 #BiocManager::install("simplifyEnrichment") #BiocManager::install("EnsDb.Hsapiens.v86")#下载包 之后 手动安装 #install.packages("~/datasets/EnsDb.Hsapien…...

webservice调用对接第三方系统

#webservice调用对接第三方系统# 最近接到一个任务&#xff0c;需要对接第三方数据&#xff0c;第三方提供对接方式的是通过webservice调用&#xff0c;webservice调用有好几种方式&#xff0c;具体可以自行了解&#xff0c;我选择的是通过wsdl文件自动生成客户端代码对接。 …...

实现不同局域网文件共享的解决方案:使用Python自带HTTP服务和端口映射

文章目录 1. 前言2. 本地文件服务器搭建2.1 python的安装和设置2.2 cpolar的安装和注册 3. 本地文件服务器的发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 数据共享作为和连接作为互联网的基础应用&#xff0c;不仅在商业和办公场景有广泛的应用…...

[Android 四大组件] --- Activity

1 Activity是什么 ​​Activity​​是一个Android的应用组件&#xff0c;它提供屏幕进行交互。每个Activity都会获得一个用于绘制其用户界面的窗口&#xff0c;窗口可以充满哦屏幕也可以小于屏幕并浮动在其他窗口之上。 一个应用通常是由多个彼此松散联系的Activity组成&…...

shell中for循环输出1-6

介绍单for循环的语法&#xff0c;以及对数字的循环使用 1、语法介绍 for 变量 in 值列表 do #执行的命令或代码块 Done其中&#xff0c;变量是用来存放每个值的变量名&#xff0c;值列表是需要遍历值的集合&#xff0c;在每次循环中&#xff0c;变量会被设置为值列表中的一…...

docker 04.更加重要的命令

之前的都是基础命令&#xff0c; 前台交互进程和后台守护进程&#xff1a; 重新进入容器&#xff1a; docker中的导入导出&#xff1a; docker中的拷贝到&#xff1a;...

【理解线性代数】(二)线性运算和线性空间

1. 从112看线性运算 11为什么等于2&#xff1f;其实11等于2有一个前提条件&#xff0c;那就是必须在线性运算规则下进行。什么是线性运算规则呢&#xff1f; 理解起来很简单&#xff0c;在一条直线上&#xff0c; 一米的直线长度一米的直线长度两米的直线长度 两个数相加的结…...

专业的视觉特效处理包,FxFactory 8 Pro for Mac助您打造精彩视频

FxFactory 8 Pro for Mac是一款强大的视觉特效处理包&#xff0c;专门为Mac用户设计。它集成了超过200种高质量的视觉效果和过渡效果&#xff0c;可以轻松地应用于各种视频项目中。该软件提供了一个直观的界面&#xff0c;用户可以通过简单拖放操作将特效应用到视频片段上。它支…...

Darshan日志分析

标头 darshan-parser 输出的开头显示了有关作业的总体信息的摘要。还可以使用–perf、–file或–total命令行选项生成其他作业级别摘要信息。 darshan log version&#xff1a;Darshan 日志文件的内部版本号。compression method&#xff1a;压缩方法。exe&#xff1a;生成日志…...

python中如何不修改字符串的前提,使其对大小写字母不敏感

如果你希望在不修改原字符串的基础上实现大小写不敏感的比较&#xff0c;你可以使用内置函数str.casefold()&#xff0c;它会将字符串转换为小写并处理一些特殊字符&#xff0c;使得比较更加严格。下面是如何使用它来实现大小写不敏感的比较&#xff1a; x input() y input()…...

聊聊Http服务化改造实践

在微服务架构体系中远程RPC调用主要包括Dubbo与Http调用两个大类&#xff0c;由于Dubbo拥有服务注册中心&#xff0c;并且起服务的命名非常规范&#xff0c;使用包名.类名.方法名进行描述。 而http调用通常都是使用httpclient等相关类库&#xff0c;这些在使用上并没有问题&am…...

docker打包部署

打包成容器命令 docker build -f ./Dockerfile-long -t 名称.打包镜像 tar docker save -o 名称.tar 名称:latest执行sudo -i&#xff0c;提示输入用户密码&#xff0c;输入密码后进入超级用户&#xff08;root&#xff09;模式 linux上传文件 rz -ytar恢复成镜像 sudo docker…...

CLIP-GmP-ViT-L-14模型部署保姆级教程:从零开始的Docker环境配置

CLIP-GmP-ViT-L-14模型部署保姆级教程&#xff1a;从零开始的Docker环境配置 你是不是也对那些能看懂图片的AI模型感到好奇&#xff1f;比如&#xff0c;你上传一张猫的照片&#xff0c;AI不仅能认出是猫&#xff0c;还能告诉你这是橘猫&#xff0c;正在晒太阳。CLIP-GmP-ViT-…...

从零构建企业级Text2Sql应用:Vanna私有化部署与Dify工作流集成

1. 企业级Text2Sql应用的核心价值 想象一下&#xff0c;财务部门的同事对着Excel表格发愁&#xff1a;"能不能帮我找出上季度华东区销售额超过50万的所有客户&#xff1f;"传统做法需要找IT部门提需求&#xff0c;等开发人员写SQL查询&#xff0c;流程可能长达数三天…...

提示工程架构师用Agentic AI,为智能城市提升品质生活

提示工程架构师&#xff1a;借助Agentic AI提升智慧城市品质生活 一、引言 (Introduction) 钩子 (The Hook) 想象一下&#xff0c;你生活在这样一个城市&#xff1a;每天清晨&#xff0c;你的智能设备会根据当天的天气、你的日程安排&#xff0c;精准推荐最适宜的衣物和出行方式…...

Arduino Nano与SSD1306实战:从静态位图到动态动画的完整实现

1. Arduino Nano与SSD1306 OLED屏入门指南 如果你手头正好有一块Arduino Nano开发板和SSD1306驱动的OLED屏幕&#xff0c;想要实现从静态图片显示到动态动画的效果&#xff0c;那这篇文章就是为你准备的。我最近在做一个智能家居项目时&#xff0c;正好用到了这个组合&#xff…...

macOS效率革命:3个全局快捷键让Finder目录操作提速300%

macOS效率革命&#xff1a;3个全局快捷键让Finder目录操作提速300% 【免费下载链接】OpenInTerminal ✨ Finder Toolbar app for macOS to open the current directory in Terminal, iTerm, Hyper or Alacritty. 项目地址: https://gitcode.com/gh_mirrors/op/OpenInTerminal…...

HarmonyOS开发入门:DevEco Studio工程目录结构详解与实战配置

HarmonyOS开发实战&#xff1a;深度解析DevEco Studio工程架构与高效配置策略 当你第一次在DevEco Studio中创建HarmonyOS项目时&#xff0c;是否曾被复杂的目录结构弄得一头雾水&#xff1f;作为华为全场景智能生态的核心开发工具&#xff0c;DevEco Studio采用了一套精心设计…...

5大核心功能解析:MAA_Punish如何实现《战双帕弥什》全自动游戏体验

5大核心功能解析&#xff1a;MAA_Punish如何实现《战双帕弥什》全自动游戏体验 【免费下载链接】MAA_Punish 战双帕弥什每日任务自动化 | Assistant For Punishing Gray Raven 项目地址: https://gitcode.com/gh_mirrors/ma/MAA_Punish MAA_Punish是一款专为《战双帕弥什…...

告别手动配置!CCSv9.3一键导入MSP430F5529LP驱动库的两种高效方法

CCSv9.3高效配置指南&#xff1a;MSP430F5529LP驱动库的自动化管理方案 每次新建CCS工程都要重复添加库文件路径&#xff1f;这种低效操作早该被淘汰了。作为TI官方推荐的开发环境&#xff0c;Code Composer Studio其实隐藏着许多能大幅提升工作效率的高级功能。本文将彻底改变…...

OpenClaw备份策略:Qwen3.5-9B重要数据自动同步到私有云盘

OpenClaw备份策略&#xff1a;Qwen3.5-9B重要数据自动同步到私有云盘 1. 为什么需要自动化备份方案 作为一个经常需要处理大量文档和代码的技术写作者&#xff0c;我经历过太多次因为系统崩溃或误操作导致工作成果丢失的惨痛教训。传统的备份方案要么需要手动操作&#xff08…...

Ubuntu下基于simple-rtsp-server构建轻量级实时视频流媒体服务

1. 为什么选择simple-rtsp-server搭建流媒体服务 最近在给公司搭建内部监控系统时&#xff0c;我对比了市面上七八种RTSP服务器方案&#xff0c;最终选择了simple-rtsp-server。这个用纯C语言编写的轻量级服务器&#xff0c;编译后二进制文件只有几百KB&#xff0c;但性能却出乎…...