一个机器人位于一个 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

提示:

m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1

解题思路

  1. 有障碍物
    1. 主要是初始化的时候麻烦
    2. 递推过程一样
  2. 初始化障碍物的网格
    1. 第一个位置
      1. dp[0][0] = 1 ;
    2. 初始化行列
      1. 需要判断
        1. if (obstacleGrid[0][c] != 1)
        2. 如果遇到石头,走不通,用默认0
        3. 如果不是石头,就取前面的值,所以如果前面的阻塞了,后面的也都走不通
  3. 动态递推
    1. 遍历
  1. /**
  2. * @param {number[][]} obstacleGrid
  3. * @return {number}
  4. */
  5. var uniquePathsWithObstacles = function (obstacleGrid) {
  6. if (obstacleGrid[0][0] == 1) return 0; // 出发点就被障碍堵住
  7. const rows = obstacleGrid.length; // 行
  8. const cols = obstacleGrid[0].length; // 列
  9. // 初始化
  10. // map无法遍历空的,要么就要用for循环
  11. const dp = new Array(rows).fill(0).map(() => new Array(cols).fill(0));
  12. // base case
  13. dp[0][0] = 1;
  14. // 第一行
  15. for (let c = 1; c < cols; c++) {
  16. // 只要当前不是障碍物,值就是1
  17. // 遇到障碍物,之后的都不会赋值为1了
  18. if (obstacleGrid[0][c] != 1) {
  19. dp[0][c] = dp[0][c - 1];
  20. }
  21. }
  22. // 第一列
  23. for (let r = 1; r < rows; r++) {
  24. if (obstacleGrid[r][0] != 1) {
  25. dp[r][0] = dp[r - 1][0];
  26. }
  27. }
  28. // 动态递推
  29. for (var r = 1; r < rows; r++) {
  30. for (var c = 1; c < cols; c++) {
  31. // 遇到障碍物不能走
  32. if (obstacleGrid[r][c] != 1) {
  33. dp[r][c] = dp[r - 1][c] + dp[r][c - 1];
  34. }
  35. }
  36. }
  37. return dp[rows - 1][cols - 1];
  38. };