题目描述
给定一个 m x n 的整数数组 grid。一个机器人初始位于左上角(即 grid[0][0])。机器人尝试移动到右下角(即 grid[m - 1][n - 1])。机器人每次只能向下或者向右移动一步。
网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含任何有障碍物的方格。
返回机器人能够到达右下角的不同路径数量。
测试用例保证答案小于等于 2 * 109。
解题思路
这是一个典型的动态规划问题,我们可以这样解决:
- 创建一个 dp 数组,
dp[i][j]
表示到达位置 (i,j) 的不同路径数
- 初始条件:
- 如果起点有障碍物,直接返回 0
- 否则
dp[0][0] = 1
- 状态转移:
- 如果当前位置有障碍物,
dp[i][j] = 0
- 否则
dp[i][j] = dp[i-1][j] + dp[i][j-1]
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution: def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: if not obstacleGrid or obstacleGrid[0][0] == 1: return 0 m, n = len(obstacleGrid), len(obstacleGrid[0]) dp = [[0] * n for _ in range(m)] dp[0][0] = 1 for j in range(1, n): if obstacleGrid[0][j] == 0: dp[0][j] = dp[0][j-1] for i in range(1, m): if obstacleGrid[i][0] == 0: dp[i][0] = dp[i-1][0] for i in range(1, m): for j in range(1, n): if obstacleGrid[i][j] == 0: dp[i][j] = dp[i-1][j] + dp[i][j-1] return dp[m-1][n-1]
|
代码详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: if not obstacleGrid or obstacleGrid[0][0] == 1: return 0 m, n = len(obstacleGrid), len(obstacleGrid[0]) dp = [[0] * n for _ in range(m)] dp[0][0] = 1 for j in range(1, n): if obstacleGrid[0][j] == 0: dp[0][j] = dp[0][j-1] for i in range(1, m): if obstacleGrid[i][0] == 0: dp[i][0] = dp[i-1][0] for i in range(1, m): for j in range(1, n): if obstacleGrid[i][j] == 0: 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),需要一个二维 dp 数组来存储中间结果
示例分析
以题目给出的示例为例:
1 2 3 4 5
| 输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] 输出:2 解释:有两种不同的路径: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右
|
举例说明
让我们用一个具体的例子来说明:
1 2 3 4 5
| obstacleGrid = [ [0,0,0], [0,1,0], [0,0,0] ]
|
- 初始化 dp 数组:
1 2 3 4 5
| dp = [ [1,0,0], [0,0,0], [0,0,0] ]
|
- 初始化第一行:
总结
这道题是经典动态规划问题的变体,关键点在于:
- 处理障碍物:遇到障碍物时路径数为 0
- 正确初始化第一行和第一列
- 利用动态规划的状态转移方程求解
通过这道题,我们可以学习到如何在动态规划问题中处理特殊情况(障碍物),以及如何正确初始化和进行状态转移。