LeetCode63. 不同路径 II

139 阅读1分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

题目

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

解题思路

这道题是不同路径问题的升级,首先我们非常肯定这是一个动态规划问题,其次它的递推方程与之前的没有什么不同,也就是dp[i][j] = dp[i - 1][j] + dp[i][j - 1],最后,我们需要注意的是处在(i,j)位置如果是障碍物,那么dp[i][j] = 0。我们只需要初始化第一列和第一行的dp数组,然后按照遍历顺序依次递推dp数组。

  1. 确定dp数组以及下标的含义

dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。

  1. 确定递推公式

想要求dp[i][j],只能从它的上方和左方来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。

  1. dp数组的初始化

如何初始化呢,原本dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理,但是本题有障碍物,我们只需要读取对应obstacleGrid,如果为1,则是有障碍物,将对应dp数组值置为0

for (let i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
       dp[i][0] = 1;
   }
   for (let i = 0; i < n && obstacleGrid[0][i] == 0; i++) {
       dp[0][i] = 1;
   }
  1. 确定遍历顺序

这里要看一下递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。此外我们还需要注意障碍问题,这里做一个判断,当 obstacleGrid[i][j]=== 1时,dp[i][j] = 0;

  1. 举例推导dp数组

var uniquePathsWithObstacles = function(obstacleGrid) {
   let m = obstacleGrid.length;
   let n = obstacleGrid[0].length;
   let dp = new Array(m).fill().map(item => Array(n).fill(0));

   for (let i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
       dp[i][0] = 1;
   }
   for (let i = 0; i < n && obstacleGrid[0][i] == 0; i++) {
       dp[0][i] = 1;
   }
   for (let i = 1; i < m; i++) {
       for (let j = 1; j < n; j++) {
            dp[i][j] = obstacleGrid[i][j] === 1 ? 0 : dp[i - 1][j] + dp[i][j - 1]
       }
   }
   return dp[m-1][n-1];
};