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
思路
第一步:确定dp数组和下标的含义
定义一个二维数组 (dp),其中 (dp[i][j]) 表示从起始点到网格中的点 ((i, j)) 有多少种不同的路径。
第二步:确定递推公式
由于机器人只能向下或向右移动,因此到达点 ((i, j)) 只有两种方式:
- 从点 ((i-1, j)) 向下移动一步。
- 从点 ((i, j-1)) 向右移动一步。
因此,递推公式为:
第三步:dp数组如何初始化
- 第一行和第一列的所有点只有一种路径可以到达(要么一直向右,要么一直向下),所以第一行和第一列的 (dp) 值都应该初始化为 1。
第四步:确定遍历顺序
由于 (dp[i][j]) 是基于 (dp[i-1][j]) 和 (dp[i][j-1]) 的,所以我们应该先填充第一行和第一列,然后从左到右、从上到下遍历整个数组。
第五步:举例推导dp数组
假设 (m = 3, n = 2),则 (dp) 数组如下:
- (dp[0][0] = 1)
- (dp[0][1] = 1)
- (dp[1][0] = 1)
- (dp[1][1] = dp[0][1] + dp[1][0] = 2)
- (dp[2][0] = 1)
- (dp[2][1] = dp[1][1] + dp[2][0] = 3)
最终结果是 (dp[2][1] = 3)。
题解
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 1));
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=dp[i][j-1]+dp[i-1][j];
}
}
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
思路
这个问题是之前网格问题的一个变种,其中添加了障碍物。依然可以使用动态规划来解决。
第一步:确定dp数组和下标的含义
定义一个二维数组 ( dp ),其中 ( dp[i][j] ) 表示从左上角(起点)到 ( (i, j) ) 的不同路径数量。
第二步:确定递推公式
如果 ( (i, j) ) 位置没有障碍物(即 ( obstacleGrid[i][j] = 0 )),则递推公式为:
如果 ( (i, j) ) 位置有障碍物(即 ( obstacleGrid[i][j] = 1 )),则 ( dp[i][j] = 0 )。
第三步:dp数组如何初始化
- 如果起点 ( (0, 0) ) 有障碍物,则 ( dp[0][0] = 0 ),否则 ( dp[0][0] = 1 )。
- 初始化第一行和第一列:如果有障碍物,则从那一点开始,该行或该列后面的所有值都应为 0。
第四步:确定遍历顺序
由于 ( dp[i][j] ) 是基于 ( dp[i-1][j] ) 和 ( dp[i][j-1] ) 的,所以应从左到右、从上到下遍历整个数组。
第五步:举例推导dp数组
假设 ( obstacleGrid = [[0, 0, 0], [0, 1, 0], [0, 0, 0]] ),则 ( dp ) 数组如下:
- ( dp[0][0] = 1 )
- ( dp[0][1] = 1 )
- ( dp[0][2] = 1 )
- ( dp[1][0] = 1 )
- ( dp[1][1] = 0 ) (有障碍物)
- ( dp[1][2] = 1 )
- ( dp[2][0] = 1 )
- ( dp[2][1] = 1 )
- ( dp[2][2] = 2 )
最终结果是 ( dp[2][2] = 2 )。
题解
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<long long>> dp(m, vector<long long>(n, 0));
// 初始化起点
dp[0][0] = (obstacleGrid[0][0] == 0) ? 1 : 0;
// 初始化第一行和第一列
for (int i = 1; i < m; ++i) {
dp[i][0] = (obstacleGrid[i][0] == 0) ? dp[i-1][0] : 0;
}
for (int j = 1; j < n; ++j) {
dp[0][j] = (obstacleGrid[0][j] == 0) ? dp[0][j-1] : 0;
}
// 动态规划
for (int i = 1; i < m; ++i) {
for (int 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];
}
};