代码随想录-Day39

62. 不同路径

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

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

问总共有多少条不同的路径?
在这里插入图片描述
输入:m = 3, n = 7
输出:28
在这里插入图片描述

方法一:

  /*** 1. 确定dp数组下标含义 dp[i][j] 到每一个坐标可能的路径种类* 2. 递推公式 dp[i][j] = dp[i-1][j] dp[i][j-1]* 3. 初始化 dp[i][0]=1 dp[0][i]=1 初始化横竖就可* 4. 遍历顺序 一行一行遍历* 5. 推导结果 。。。。。。。。** @param m* @param n* @return*/public static 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 i = 0; i < n; i++) {dp[0][i] = 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];}

这段代码是使用Java实现解决“机器人行走的路径数目”问题,即在一个m x n的网格中,从左上角(0,0)到右下角(m-1,n-1)有多少种行走路径,每次只能向右或向下移动。该问题可以用动态规划(Dynamic Programming, DP)来解决。

代码解析

  1. 确定dp数组下标含义dp[i][j] 表示到达网格中坐标为(i, j)位置的不同路径数目。

  2. 递推公式:到达(i, j)位置的路径数等于从(i-1, j)位置过来的路径数加上从(i, j-1)位置过来的路径数,即 dp[i][j] = dp[i-1][j] + dp[i][j-1]。这是因为机器人到达(i, j)只能是从(i-1, j)向右走一步或从(i, j-1)向下走一步。

  3. 初始化:边界条件是网格的第一行和第一列,因为从这些边缘出发到它们自身的路径只有一条,即dp[i][0]=1(第一列)和dp[0][i]=1(第一行)。

  4. 遍历顺序:按照从上到下、从左到右的顺序遍历网格,先处理好边界和第一行第一列后,逐行逐列计算内部点的路径数目。

  5. 推导结果:最终,dp[m-1][n-1]即为到达右下角的路径总数。

示例

假设m=3n=3,即一个3x3的网格,按照上述代码执行,dp数组会逐步填充如下:

初始状态(考虑初始化):

1 1 1
1 1 1
1 1 1

迭代填充后(忽略边界,根据递推公式):

1 2 3
1 3 6
1 4 10

最终,dp[2][2] = 10,表示从左上角到右下角有10种不同的行走路径。

通过这个动态规划方法,我们可以高效地解决这类路径计数问题。

方法二:

class Solution {public int uniquePaths(int m, int n) {// 在二维dp数组中,当前值的计算只依赖正上方和正左方,因此可以压缩成一维数组。int[] dp = new int[n];// 初始化,第一行只能从正左方跳过来,所以只有一条路径。Arrays.fill(dp, 1);for (int i = 1; i < m; i ++) {// 第一列也只有一条路,不用迭代,所以从第二列开始for (int j = 1; j < n; j ++) {dp[j] += dp[j - 1]; // dp[j] = dp[j] (正上方)+ dp[j - 1] (正左方)}}return dp[n - 1];}
}

这段Java代码是解决“机器人行走的路径数目”问题的另一种实现,采用了一维动态规划数组来减少空间复杂度。给定一个m x n的网格,从左上角(0,0)到右下角(m-1,n-1)有多少种行走路径,每次只能向右或向下移动。下面是代码的详细解析:

代码解析

  1. 初始化一维dp数组:由于计算某个位置的路径数只与其正上方和正左方的路径数有关,因此可以使用一维数组dp来存储到达每列底部的路径总数。数组长度为n,初始化时考虑到第一行的每个位置都只有1条路径(即自己到自己),所以使用Arrays.fill(dp, 1);初始化。

  2. 双层循环遍历:外层循环遍历网格的行(从1开始,因为第一行已经初始化),内层循环遍历网格的列(从1开始,因为第一列在初始化时已设定为1)。

  3. 状态转移方程:对于dp[j],即到达第i行第j列的路径数,可以通过累加左边一格的路径数dp[j - 1]得到,即dp[j] += dp[j - 1];。这样做是因为到达(i, j)的路径可以看作是从(i - 1, j)向下走一条路径加上从(i, j - 1)向右走一条路径的所有组合。

  4. 返回结果:遍历完成后,dp[n - 1]存储了到达右下角的路径总数,直接返回这个值即可。

优势

  • 空间优化:相比于二维数组的解法,这里只使用了一维数组来存储每行的结果,从而将空间复杂度从O(mn)降低到了O(n),对于大规模的m和n来说,这是一个显著的优势。
  • 计算逻辑简洁:通过巧妙地复用一维数组,避免了额外的空间开销,同时也保持了逻辑的直观性。

示例

假设m=3n=3,执行上述代码后,dp数组会经历以下变化:

  • 初始化后:dp = [1, 1, 1]
  • 第一轮外层循环后:dp = [1, 2, 3] (到达第二行各列的路径数)
  • 第二轮外层循环后:dp = [1, 3, 6] (到达第三行各列的路径数,最终结果)

最终返回dp[n - 1] = 6,表示从左上角到右下角有6种不同的行走路径。

63. 不同路径 II

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

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

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。
在这里插入图片描述
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右
    在这里插入图片描述
    输入:obstacleGrid = [[0,1],[0,0]]
    输出:1

方法一:

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

这段Java代码是用于解决“有障碍的格子”的独特路径问题。给定一个二维数组obstacleGrid,其中0表示可以通过的格子,1表示障碍物。你要从左上角(0,0)移动到右下角(m-1, n-1),每次只能向右或向下移动。该函数计算并返回从起点到终点的不同路径数目,如果无法到达终点则返回0。

代码解析:

  1. 初始化变量:首先获取网格的行数m和列数n,并创建一个与obstacleGrid同样大小的二维数组dp来存储到达每个格子的路径数。

  2. 检查起点和终点:如果终点或起点有障碍物,直接返回0,因为这意味着没有路径可达。

  3. 初始化边界条件:遍历第一列和第一行,如果格子不是障碍物,将其路径数设为1。这表示从起点开始向右或向下有一条路径。

    • 对于第一列:dp[i][0] = 1(若无障碍)
    • 对于第一行:dp[0][j] = 1(若无障碍)
  4. 动态规划填充dp数组:从第二行和第二列开始,对于每个格子(i, j),如果该格子不是障碍物,则其路径数为上面格子(i-1, j)的路径数加上左边格子(i, j-1)的路径数,即dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。如果遇到障碍物,则该位置的路径数设为0,因为不能通过。

  5. 返回结果:最后,dp[m - 1][n - 1]存储了到达终点的路径数目,返回该值作为结果。

示例

假设obstacleGrid为:

[[0, 0, 0],[0, 1, 0],[0, 0, 0]
]

运行这段代码会返回2,因为从左上角到右下角只有两条路径可走,且中间的障碍物阻止了其他可能的路径。

方法二:

// 空间优化版本
class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int m = obstacleGrid.length;int n = obstacleGrid[0].length;int[] dp = new int[n];for (int j = 0; j < n && obstacleGrid[0][j] == 0; 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 - 1];}}}return dp[n - 1];}
}

这段代码是针对“有障碍的格子”的独特路径问题的空间优化版本。与之前的解决方案相比,这里使用了一维数组dp来代替二维数组,从而节省了空间。代码依然计算从二维数组obstacleGrid的左上角到右下角的无障碍路径数量,其中1表示障碍物,0表示可通过的路径。

代码解析

  1. 初始化变量:获取网格的行数m和列数n,并声明一个一维数组dp,长度为n,用于记录到达当前列的路径数。

  2. 初始化第一行:遍历第一行的列,只要遇到无障碍物(obstacleGrid[0][j] == 0),就将dp[j]设为1,表示从起点到这一列有一条路径。

  3. 动态规划填充dp数组

    • 遍历每一行(从第二行开始),对于每一行中的每一列:
      • 如果当前格子是障碍物,那么到达该格子的路径数为0,因此dp[j] = 0
      • 如果当前格子不是障碍物,有两种情况:
        • 如果是第一列(j == 0),则只能从上方到达,因此dp[j] = dp[j](保持不变,实际上这种情况在循环外已处理,此处默认处理下一列的情况)。
        • 如果不是第一列,到达当前格子的路径数等于上方格子的路径数加上左侧格子的路径数(因为只能向上或向左移动),即dp[j] += dp[j - 1]
  4. 返回结果:最后返回dp[n - 1],即到达终点的路径数量。

优点

  • 空间优化:相比使用二维数组的解法,这里仅使用一维数组存储每行的路径数,将空间复杂度从O(mn)降低到O(n),在处理大尺寸矩阵时更加高效。

示例

假设obstacleGrid为:

[[0, 0, 0],[0, 1, 0],[0, 0, 0]
]

该代码会返回2,表示有两条路径可以从左上角走到右下角,且避开了中间的障碍物。

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

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

相关文章

线程安全问题(一)——锁的简单使用

多线程安全问题 线程安全问题的引入案例引入多线程指令排序问题 线程不安全的原因解决线程不安全的方法锁的引入上锁和解锁过程一个简单的锁Demo对这个案例进行几次修改 总结 线程安全问题的引入 在前面的博文中&#xff0c;我们了解到通过Thread.join()的方法让线程进入等待&…

统信UOS系统忘记登录密码怎么办

在使用统信操作系统UOS的时候有可能会出现忘记密码的情况&#xff0c;当遇到了用户登录密码忘记时如何修改&#xff1f;今天分享一下忘记超级系统管理员Root以及普通密码时的解决方法。 因为UOS系统版本的原因&#xff0c;UOS 1031操作系统取消了单用户更改密码的方法&#xff…

jupyter notebook的markdown语法不起作用

在这个界面编辑&#xff0c;发现markdown你编辑的是什么就是什么&#xff0c;不起作用&#xff0c;然而点一下&#xff1a; 右上角“Notebook转发”&#xff0c;就会单独跳出一个jupyter notebook的界面&#xff0c;此时就会奏效&#xff1a;

【CT】LeetCode手撕—72. 编辑距离

目录 题目1- 思路动规五部曲 2- 实现⭐72. 编辑距离——题解思路 3- ACM 实现 题目 原题连接&#xff1a;72. 编辑距离 1- 思路 模式识别&#xff1a;编辑举例 ——> 动态规划 动规五部曲 1.dp数组的含义 int[][] dp new int[word1.length()][word2.length()];以 i-1 …

6-47选择整数计算

整数计算&#xff1a; 用swing组件来实现整数计算&#xff0c;需要对整数计算的值进行校验。 import javax.swing.*; import java.awt.*; import java.awt.event.*;public class IntegerCalculator extends JFrame implements ActionListener {private JCheckBox[] checkBoxe…

【分布式文件系统HDFS】文件操作基本命令的使用

目录 一、按照下述要求写出相应的文件操作命令&#xff0c;执行并观察结果 1. 新建目录 1.1 在本地文件系统按要求创建如下的文件夹 1.2 在HDFS文件系统按要求创建如下的文件夹 2. 编辑文件test1.txt&#xff0c;放入本地文件夹 /opt/user/myfile 3. 使用moveFromLocal命令…

本地部署大模型的简单方法

https://ollama.com/https://ollama.com/ 在本地安装ollama windows版本。安装好后&#xff0c;就可以验证大模型了。 可以先测试一下qwen 0.5b&#xff0c;打开cmd&#xff0c;执行ollama run qwen:0.5b&#xff0c;首次会下载大模型的模型资源。 模型下好后就可以交互…

H5、Vue3、UniApp实现抖音短视频功能

H5、Vue3、UniApp实现抖音短视频功能 ml-swiper https://ext.dcloud.net.cn/plugin?id18973 可 0 配置&#xff0c;高性能、低代码、全端兼容 APP端效果图 微信小程序端效果图 Vue网页端效果图 ml-swiper 可 0 配置&#xff0c;高性能、低代码、全端兼容 APP端效果图 …

扩散模型 GLIDE:35 亿参数的情况下优于 120 亿参数的 DALL-E 模型

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

媒体邀约中媒体采访应该如何做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 在媒体邀约中&#xff0c;媒体采访应该遵循以下几个步骤和…

Python读取中文路径,出现乱码问题解决方案

Python读取中文路径&#xff0c;出现乱码问题解决方案 一、问题描述二、问题解决 欢迎学习交流&#xff01; 邮箱&#xff1a; z…1…6.com 网站&#xff1a; https://zephyrhours.github.io/ 一、问题描述 笔者在使用opencv读取带有中文路径的图片时&#xff0c;发现会出现乱…

C++ 模板:全特化和偏特化

目录 全特化&#xff08;Full Specialization&#xff09; 偏特化&#xff08;Partial Specialization&#xff09; 特点和使用场景 注意事项 在C中&#xff0c;模板特化&#xff08;template specialization&#xff09;是一种强大的功能&#xff0c;允许对模板进行特定情…

2024最新算法:鳗鱼和石斑鱼优化(Eel and grouper optimizer,EGO)算法求解23个函数,MATLAB代码

一、算法介绍 鳗鱼和石斑鱼优化器&#xff08;Eel and grouper optimizer&#xff0c;EGO&#xff09;是2024年提出的一种智能优化算法&#xff0c;EGO算法的灵感来自海洋生态系统中鳗鱼和石斑鱼的共生相互作用和觅食策略。 参考文献&#xff1a; [1]A. Mohammadzadeh, S. Mi…

玩转数据库索引

1、概述 通常我们要对数据库进行优化&#xff0c;主要可以通过以下五种方法。 计算机硬件调优应用程序调优数据库索引优化SQL语句优化事务处理调优 本篇文章将向大家介绍数据库中索引类型和使用场合&#xff0c;本文以SQL Server为例&#xff0c;对于其他技术平台的朋友也是有…

DDL-表操作-数据类型

一.DDL-表操作-数据类型 MySQL中的数据类型有很多,主要分为三类:数值类型,字符串类型,日期类型。 二.关系表 注意: 无符号和有符号的取值范围不是一样的,无符号需要加上UNSIGNED范围。 BLOB&#xff1a;用来描述二进制数据 TEXT:用来描述字符串 三.定长字符串和变长字符串 c…

【STM32入门学习】学习嵌入式实时操作系统(RTOS)移植uc/OS到stm32F103上

目录 一、建立STM32HAL库工程 1.1实时操作系统 1.2基于HAL库创建工程 二、获取uC/OS-III源码 三、移植准备 3.1复制uC/OS-III文件到工程文件夹 3.2添加工程组件和头文件路径 四、移植修改代码 &#xff14;.1.启动文件修改&#xff1a; &#xff14;.2.app_cfg.h &a…

Java Scanner 类

Java Scanner 类 java.util.Scanner 是 Java5 的新特征&#xff0c;我们可以通过 Scanner 类来获取用户的输入。 下面是创建 Scanner 对象的基本语法&#xff1a; Scanner s new Scanner(System.in);接下来我们演示一个最简单的数据输入&#xff0c;并通过 Scanner 类的 nex…

关于FPGA对 DDR4 (MT40A256M16)的读写控制 4

关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 4 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado、Quartus II 关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 4一、引言二、DDR4 SDRAM设备中模式寄存器重要的模式寄存…

数组中的逆序对

描述&#xff1a; https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/description/ 思路&#xff1a; 在进行归并排序时&#xff0c;会分成有序的左右两部分&#xff0c;如果左部分出现了大于右部分的数时&#xff08;nums[cur1] > nums[cur2]&#xff09;&…

Javaweb配置tomcat

Tomcat 9版本链接 链接&#xff1a;https://pan.baidu.com/s/1u-eDur5KlqlXM_IM50Ahtg?pwd1njm 提取码&#xff1a;1njm 1、打开idea&#xff0c;创建maven项目 2023版IDEA 2、 目录结构 ps: 如果结果不完整,选中main右键 新建对应的文件夹 3、 web项目设置Tomcat(部署项目…