题目链接: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
文章讲解:代码随想录
视频讲解:动态规划,这次遇到障碍了| LeetCode:63. 不同路径 II_哔哩哔哩_bilibili
题解1:动态规划
思路:方法和 LeetCode 62. 不同路径 类似,区别在于 dp 数组的初始化不同。遇到障碍时,dp[i][j] 直接设为0。
动态规划分析:
- dp 数组以及下标的含义:dp[i][j] 代表到达 (i, j) 格子的走法数量。
- 递推公式:遇到障碍,dp[i][j] = 0,否则 dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。
- dp 数组初始化:第0行和第0列遇到障碍前初始化为1,障碍即后面都初始化为0。
- 遍历顺序:从上到下,从左到右。
- 打印 dp 数组:以输入 [[0,0,0],[0,1,0],[0,0,0]] 为例,dp 数组为 [ [ 1, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 2 ] ]。
/**
* @param {number[][]} obstacleGrid
* @return {number}
*/
var uniquePathsWithObstacles = function(obstacleGrid) {
const m = obstacleGrid.length;
const n = obstacleGrid[0].length;
// 定义 dp 数组
const dp = new Array(m).fill().map(() => new Array(n).fill(0));
// dp 数组初始化
for (let i = 0; i < m; i++) {
if (obstacleGrid[i][0] === 1) {
break;
}
dp[i][0] = 1;
}
for (let j = 0; j < n; j++) {
if (obstacleGrid[0][j] === 1) {
break;
}
dp[0][j] = 1;
}
// 使用递推公式填充 dp 数组
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (obstacleGrid[i][j] === 1) {
dp[i][j] = 0;
} else {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m - 1][n - 1];
};
分析:时间复杂度为 O(m * n),空间复杂度为 O(m * n)。
收获
练习使用动态规划法求解路径问题。