力扣63. 不同路径 II
题目来源(力扣):
https://leetcode.cn/problems/unique-paths-ii/description/
题目描述:
一个机器人位于一个 m x n 网格的左上角 。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。
其中有些网格有障碍物,不可以经过。
问总共有多少条不同的路径?
基本思路:
和 力扣62. 不同路径 几乎相同 https://leetcode.cn/problems/unique-paths/description/
只是多了障碍物,特殊处理即可。
数组定义、遍历顺序都不变,只是在初始化和dp数组求解过程中,对于障碍物进行了处理。
初始化步骤中,如果第0行的某个位置有障碍物,则该位置及其之后的位置都不可到达;第0列同理。
dp数组求解过程中,如果位置(i,j)是障碍物,则直接跳过该位置(并且dp[i][j]=0)即可
代码实现:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
// 1.定义dp数组
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// 2.确定递推方程
// dp[i][j]=dp[i-1][j]+dp[i][j-1];
// 3.初始化
for (int i = 0; i < m; i++) { // 初始化第一列
if (obstacleGrid[i][0])
break; // 遇见障碍物,则之后的所有的位置都不可以到达
dp[i][0] = 1;
}
for (int j = 0; j < n; j++) { // 初始化第一行
if (obstacleGrid[0][j])
break; // 遇见障碍物,则之后所有的位置都不可以到达
dp[0][j] = 1;
}
// 4.确定递推顺序 左上到右下
// 左上到右下,但是优先行
// for(int i=1;i<m;i++){
// for(int j=1;j<n;j++){
// if(obstacleGrid[i][j]){
// //dp[i][j]=0;//这句可以不写,因为默认为0
// continue;
// }
// dp[i][j]=dp[i-1][j]+dp[i][j-1];
// }
// }
// 左上到右下,但是优先列
for (int j = 1; j < n; j++) {
for (int i = 1; i < m; i++) {
if (obstacleGrid[i][j]) {
// dp[i][j]=0;//这句可以不写,因为默认为0
continue;
}
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
// 5.打印(部分)dp数组以确定是否符合预期
// for(int i=0;i<m;i++){
// for(int j=0;j<n;j++)
// cout<<dp[i][j]<<" ";
// cout<<endl;
// }
return dp[m - 1][n - 1];
}
};
时间复杂度
O(m*n)
补充
和力扣62. 不同路径相似,此题dp数组依旧可以压缩为1维的。
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
// 1.定义dp数组
vector<int> dp(n + 1);
// 2.确定递推方程
// dp[j]=dp[j]+dp[j-1];
// 3.初始化
for (int j = 0; j < n; j++) { // 初始化第一行
if (obstacleGrid[0][j])
break; // 遇见障碍物,则之后所有的位置都不可以到达
dp[j] = 1;
}
// 4.确定递推顺序 左上到右下
// 左上到右下,优先行
for (int i = 1; i < m; i++) {
if (obstacleGrid[i][0])
dp[0] = 0; // 每行第一个位置特殊判定一下
for (int j = 1; j < n; j++) {
if (obstacleGrid[i][j]) {
dp[j] = 0; //此时不能省略,因为二位dp数组有默认值0,而1维dp数组需要手动维护
continue;
}
dp[j] = dp[j] + dp[j - 1];
// cout<<dp[j]<<" "; //5.打印(部分)dp数组以确定是否符合预期
}
// cout<<endl;
}
return dp[n - 1];
}
};
浙公网安备 33010602011771号