1. 题目
读题
https://leetcode.cn/problems/unique-paths/
考查点
这道题的考查点主要是**动态规划**的思想,也就是把一个复杂的问题分解成多个子问题,用一个数组或矩阵来存储子问题的解,然后通过状态转移方程来求解最终的问题。¹²⁴
动态规划的难点在于找到合适的状态转移方程,也就是如何从已知的子问题的解推导出更大的子问题的解,直到得到最终问题的解。¹²⁴
这道题还可以用**排列组合**的方法来解决,也就是利用数学公式来计算从左上角到右下角需要走多少步,然后在这些步数中选择向下或向右走的步数,求出所有可能的组合数。²
这种方法的难点在于避免溢出,也就是要注意阶乘运算可能会超过整数范围,需要用更大的数据类型或者优化计算过程。²
2. 解法
思路
这道题的解答思路是这样的:
首先,我们可以用一个二维数组dp[m][n]来存储到达每个格子的路径数,初始条件是dp[0][0] = 1,表示从左上角到左上角只有一种路径。
然后,我们可以遍历每个格子,根据它的位置来更新dp数组的值。有三种情况:
- 如果格子在第一行,那么它只能从左边的格子来,所以dp[i][j] = dp[i][j-1]。
- 如果格子在第一列,那么它只能从上面的格子来,所以dp[i][j] = dp[i-1][j]。
- 如果格子在其他位置,那么它可以从左边或上面的格子来,所以dp[i][j] = dp[i-1][j] + dp[i][j-1]。
最后,我们返回dp[m-1][n-1],就是右下角的值,也就是从左上角到右下角的路径数。
代码逻辑
代码的逻辑是这样的:
首先,我们创建一个二维数组dp,用来存储到达每个格子的路径数,初始化为1,表示每个格子都至少有一种路径。
然后,我们用两个嵌套的for循环来遍历每一行和每一列,从第二行和第二列开始,因为第一行和第一列已经初始化了。
对于每个格子,我们判断它是否在第一行或第一列,如果是,那么它只能从左边或上面来,所以我们把左边或上面的值赋给它。如果不是,那么它可以从左边或上面来,所以我们把左边和上面的值相加赋给它。
最后,我们返回dp[m-1][n-1],就是右下角的值,也就是从左上角到右下角的路径数。
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Solution { public int uniquePaths( int m, int n) { int [][] dp = new int [m][n]; // 创建二维数组 dp[ 0 ][ 0 ] = 1 ; // 初始条件 for ( int i = 0 ; i < m; i++) { // 遍历每一行 for ( int j = 0 ; j < n; j++) { // 遍历每一列 if (i == 0 && j == 0 ) continue ; // 跳过左上角 if (i == 0 ) { // 第一行,只能从左边来 dp[i][j] = dp[i][j- 1 ]; } else if (j == 0 ) { // 第一列,只能从上面来 dp[i][j] = dp[i- 1 ][j]; } else { // 其他情况,从左边或上面来 dp[i][j] = dp[i- 1 ][j] + dp[i][j- 1 ]; } } } return dp[m- 1 ][n- 1 ]; // 返回右下角的值 } } |
3. 总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-05-01 java中的12种锁
2019-05-01 公平锁与非公平锁
2019-05-01 设计模式:门面模式(Facade)
2019-05-01 设计模式:装饰者模式
2019-05-01 设计模式:组合模式
2019-05-01 设计模式:桥接模式
2019-05-01 设计模式:适配器模式(Adapter)