62. 不同路径
题目描述:一个机器人位于一个
m x n
网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7 输出:28示例 2:
输入:m = 3, n = 2 输出:3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 3. 向下 -> 向右 -> 向下示例 3:
输入:m = 7, n = 3 输出:28示例 4:
输入:m = 3, n = 3 输出:6提示:
1 <= m, n <= 100
- 题目数据保证答案小于等于
2 * 109
代码思路:
-
状态定义: 使用一个二维数组
dp
来存储每个位置(i, j)到达该位置的唯一路径数。 -
边界条件: 对于第一行和第一列,到达这些位置的路径数都是 1,因为只有一种路径可以到达。先将
dp[0][j]
和dp[i][0]
全部设为 1。 -
状态转移: 对于其他位置
(i, j)
,它的路径数等于从上方(i-1, j)
到达和从左方(i, j-1)
到达的路径数之和,即dp[i][j] = dp[i-1][j] + dp[i][j-1]
。 -
返回结果: 最终返回
dp[m-1][n-1]
,这就是从左上角到右下角的唯一路径数。
这个动态规划将一个复杂的问题拆解为一系列更小的子问题,并利用子问题的解来构建出原问题的解。算法的时间复杂度是 O(mn),需要填充整个 dp
数组,空间复杂度也是 O(mn),使用了一个二维数组来存储中间状态。
class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[m][n];Arrays.fill(dp[0], 1);for (int i = 1; i < m; i++) {dp[i][0] = 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];}
}
63. 不同路径 II
题目描述:
一个机器人位于一个
m x n
网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用
1
和0
来表示。示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] 输出:2 解释:3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2条不同的路径: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右示例 2:
输入:obstacleGrid = [[0,1],[0,0]] 输出:1提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j]
为0
或1
代码思路:
-
状态定义: 与之前的"唯一路径数"问题类似,使用一个二维数组
dp
来存储每个位置(i, j)到达该位置的唯一路径数。 -
边界条件:
- 如果当前位置是障碍物(
obstacleGrid[i][j] == 1
),那么到达该位置的路径数为 0。 - 如果是左上角(i, j) = (0, 0),且该位置不是障碍物,那么到达该位置的路径数为 1。
- 如果是第一行或第一列,且该位置不是障碍物,那么到达该位置的路径数等于其左侧或上方位置的路径数。
- 如果当前位置是障碍物(
-
状态转移: 对于其他位置
(i, j)
,它的路径数等于从上方(i-1, j)
到达和从左方(i, j-1)
到达的路径数之和,即dp[i][j] = dp[i-1][j] + dp[i][j-1]
。 -
返回结果: 返回
dp[m-1][n-1]
,这就是从左上角到右下角的唯一路径数。
这个动态规划算法的时间复杂度仍然是 O(mn),需要填充整个 dp
数组。空间复杂度也是 O(mn),使用了一个二维数组来存储中间状态。这个问题与之前的"不同路径"问题的主要区别在于需要处理障碍物的情况。通过在状态转移方程中增加对障碍物的判断,来确保在有障碍物的情况下,到达某个位置的路径数为 0。
class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int m = obstacleGrid.length;int n = obstacleGrid[0].length;int[][] dp = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (obstacleGrid[i][j] == 1) {dp[i][j] = 0;} else if (i == 0 && j == 0) {dp[0][0] = 1 - obstacleGrid[0][0];} else if (i == 0) {dp[i][j] = dp[0][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];}
}