63. 不同路径 II - 力扣(LeetCode)
题目要求:
给定一个 m x n
的整数数组 grid
。一个机器人初始位于 左上角(即 grid[0][0]
)。机器人尝试移动到 右下角(即 grid[m - 1][n - 1]
)。机器人每次只能向下或者向右移动一步。
网格中的障碍物和空位置分别用 1
和 0
来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。
返回机器人能够到达右下角的不同路径数量。
测试用例保证答案小于等于 2 * 109
。
示例 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
解法-1 动态规划 O(N)
这个题与每日一练:不同路径-CSDN博客十分相似,只是多了障碍物,只需要在遇到障碍物时作特殊处理即可:
class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();int n = obstacleGrid[0].size();vector<vector<int>> dp(m+1,vector<int>(n+1));dp[0][1] = 1;for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){if(obstacleGrid[i-1][j-1] == 1) // 遇到障碍物{dp[i][j] == 0; // 置0表示没有路径能经过这个节点continue;}dp[i][j] = dp[i-1][j]+dp[i][j-1];}}return dp[m][n];}
};
优化-使用滑动数组减少内存开销:
求某一个位置的路径数量时,我们只使用了它上面格和右面格的格子,所以可以只创建一个数组dp保存上一层的节点路径数,b保存前一格的节点路径数,a为当前格子的路径数。
每次给a赋值时,如果a是障碍物就赋0,否则a = b+dp[ j ]
给a赋值完毕后更新b:b = a;更新dp[ j ]:dp[ j ] = a;
图示如下:
class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();int n = obstacleGrid[0].size();vector<int> dp(n);dp[0] = 1;int a, b;for (int i = 0; i < m; i++) {b = 0; // 在最右边,没有右一格就是0for (int j = 0; j < n; j++) {if (obstacleGrid[i][j] == 1) {a = 0;} else {a = dp[j] + b;}// 更新b = a;dp[j] = a;}}return a;}
};