返回

LeetCode - #63 不同路径 II 解密

前端

LeetCode - #63 不同路径 II:这是一场智力博弈

LeetCode #63 不同路径 II 难题旨在考验您解决复杂问题的能力,它要求您计算机器人从左上角移动到右下角的不同路径数量。但不同于经典的 #62 不同路径,#63 不同路径 II 引入了障碍物。这些障碍物就像散落在棋盘上的雷区,挡住了机器人的去路。您需要巧妙地避开障碍物,找到所有可能的路径。

披荆斩棘,算法策略大解密

为了攻克这道难题,您需要借助动态规划的思想。动态规划是一种将问题分解为一系列重叠子问题,并逐步解决这些子问题的方法。在这个过程中,您可以利用先前计算的结果来解决后续的子问题,从而大大提高效率。

在本文中,我们将采用自顶向下的动态规划方法。我们首先将整个棋盘视为一个网格,然后从右下角开始,逐步计算每个网格的不同路径数量。对于每个网格,我们可以根据其所在的位置和周围的障碍物情况,计算出到达该网格的不同路径数量。

Python 代码,逐行剖析

def uniquePathsWithObstacles(obstacleGrid):
    m, n = len(obstacleGrid), len(obstacleGrid[0])
    dp = [[0] * n for _ in range(m)]

    # 初始化第一行和第一列
    for i in range(m):
        if obstacleGrid[i][0] == 1:
            break
        dp[i][0] = 1
    for j in range(n):
        if obstacleGrid[0][j] == 1:
            break
        dp[0][j] = 1

    # 动态规划计算其余网格
    for i in range(1, m):
        for j in range(1, n):
            if obstacleGrid[i][j] == 1:
                dp[i][j] = 0
            else:
                dp[i][j] = dp[i-1][j] + dp[i][j-1]

    # 返回右下角网格的不同路径数量
    return dp[m-1][n-1]

让我们逐行分析这段代码:

  • def uniquePathsWithObstacles(obstacleGrid)::这是函数定义,它接受一个参数 obstacleGrid,即包含障碍物的网格。
  • m, n = len(obstacleGrid), len(obstacleGrid[0])::这两行代码计算网格的行数和列数,并分别存储在变量 mn 中。
  • dp = [[0] * n for _ in range(m)]::这行代码创建一个二维列表 dp,其中每个元素都初始化为 0。dp 列表将用于存储每个网格的不同路径数量。
  • # 初始化第一行和第一列:这两组循环负责初始化第一行和第一列的 dp 列表。由于机器人只能从左上角出发,因此第一行和第一列的网格都只有唯一一条路径到达。
  • # 动态规划计算其余网格:这组循环用于计算其余网格的不同路径数量。对于每个网格,如果它不是障碍物,那么它的不同路径数量等于其上方网格和左侧网格的不同路径数量之和。如果它是一个障碍物,那么它的不同路径数量为 0。
  • # 返回右下角网格的不同路径数量:最后,我们返回右下角网格的不同路径数量,即 dp[m-1][n-1]

结语

LeetCode - #63 不同路径 II 是一道经典的动态规划难题。通过运用自顶向下的动态规划方法,我们成功地解决了这个问题。如果您想进一步提高您的编程能力,我强烈推荐您尝试更多 LeetCode 难题。祝您一路顺风,在算法世界中不断进步!