返回

LeetCode 题解:63. 不同路径 II,JavaScript 详细教程,动态规划

前端

众所周知,动态规划算法是一项重要且常见的编程技巧,在各种算法问题中有着广泛的应用,而 LeetCode 则是备受程序员青睐的编程题网站。因此,掌握 LeetCode 中的动态规划问题不仅能够提升你的算法能力,还能让你在面试中脱颖而出。

今天,我们将着眼于 LeetCode 上的第 63 道题目:不同路径 II。在这道题中,你将面对一个包含障碍物的网格,需要计算从网格左上角走到右下角的不同路径数量。

问题

在一个大小为 m x n 的网格中,每个单元格可以是以下三种状态之一:

  • 可通行:你可以通过这个单元格。
  • 障碍物:你无法通过这个单元格。
  • 起点:你只能从这个单元格开始移动。
  • 终点:你只能在这个单元格结束移动。

你需要计算从起点走到终点有多少条不同的路径。如果从起点到终点不存在路径,则返回 0。

动态规划解法:

动态规划是一种自底向上的解题方法,它将问题分解成一系列子问题,然后逐步解决这些子问题,最终得到整个问题的解。对于 LeetCode 63. 不同路径 II,我们可以使用动态规划的思想来解决问题。

具体步骤如下:

  1. 定义动态规划状态

    dp[i][j] 表示从网格左上角走到单元格 (i, j) 的不同路径数量。

  2. 边界条件

    • 对于障碍物单元格,即 grid[i][j] == 1,则 dp[i][j] = 0
    • 对于第一行和第一列的单元格,由于它们只能从一个方向移动,因此 dp[i][0] = 1dp[0][j] = 1
    • 对于起点单元格,由于它只能从一个方向移动,因此 dp[0][0] = 1
  3. 动态规划递推公式

    对于非障碍物单元格,即 grid[i][j] == 0,则 dp[i][j] 可以从上面和左面的单元格转移而来,因此:

    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
    
  4. 返回结果

    最终,问题的解即为 dp[m - 1][n - 1]

代码实现

/**
 * @param {number[][]} grid
 * @return {number}
 */
const uniquePathsWithObstacles = (grid) => {
  if (grid[0][0] === 1) {
    return 0;
  }

  const m = grid.length;
  const n = grid[0].length;

  const dp = new Array(m).fill(0).map(() => new Array(n).fill(0));
  dp[0][0] = 1;

  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      if (grid[i][j] === 1) {
        dp[i][j] = 0;
      } else if (i === 0 || j === 0) {
        dp[i][j] = 1;
      } else {
        dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
      }
    }
  }

  return dp[m - 1][n - 1];
};

复杂度分析

  • 时间复杂度:O(m * n),其中 m 和 n 分别为网格的长和宽。
  • 空间复杂度:O(m * n),其中 m 和 n 分别为网格的长和宽。

通过这个详细的 JavaScript 代码示例,你将彻底理解如何使用动态规划算法来解决 LeetCode 题库中的不同路径 II 这类问题。如果你想进一步深入学习动态规划,可以搜索其他相关的编程教程和资源,不断提升自己的算法能力。