题目:
- 一个机器人位于一个
m x n
网格的左上角 (起始点在下图中标记为 “Start” )。 - 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
- 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
- 网格中的障碍物和空位置分别用
1
和0
来表示。
示例:
- 输入: obstacleGrid = [ [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 0 ] ] [[0,0,0],[0,1,0],[0,0,0]] [[0,0,0],[0,1,0],[0,0,0]]
- 输出: 2 2 2
- 解释: 3x3 网格的正中间有一个障碍物。从左上角到右下角一共有 2 条不同的路径:
- 向右 -> 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右 -> 向右
解题思路:
- 确定dp数组及下标的含义:
dp[i][j]
表示从 ( 0 , 0 ) (0, 0) (0,0) 触发,到 ( i , j ) (i, j) (i,j) 有dp[i][j]
条不同的路径。 - 确定递推公式: 由于题意,只能 向下 或 向右 走,因此可以从两个方向来推导出
dp[i][j]
,即从dp[i - 1][j]
和dp[i][j - 1]
。dp[i - 1][j]
表示从 ( 0 , 0 ) (0,0) (0,0) 到 ( i − 1 , j ) (i - 1, j) (i−1,j) 有多少条路径;dp[i][j - 1]
表示从 ( 0 , 0 ) (0, 0) (0,0) 到 ( i , j − 1 ) (i, j - 1) (i,j−1) 有多少条路径。因此将这两个方向的路径数 相加,即为dp[i][j]
的值。 - dp数组初始化: 首先
dp[i][0]
一定都是1, 因为从 ( 0 , 0 ) (0, 0) (0,0) 的位置到 ( i , 0 ) (i, 0) (i,0) 的路径只有一条,但若是遇到故障,那么故障后的路径初始为 0,因为此路不通了,dp[0][j]
同理。 - 确定遍历顺序: 从递推公式
dp[i][j] = dp[i - 1][j] + d[i][j - 1]
中可以看出,一定是从左到右一层一层遍历,这样保证推导dp[i][j]
的时候,dp[i - 1][j]
和dp[i][j - 1]
一定是有值的。
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> dp(m, vector<int>(n, 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++)
{
if(obstacleGrid[i][j] == 1) continue;
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
return dp[m - 1][n - 1];
}
};
时间复杂度:
O
(
n
×
m
)
O(n×m)
O(n×m)
空间复杂度:
O
(
n
×
m
)
O(n×m)
O(n×m)