题目
A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
Note: m and n will be at most 100.
Example 1:
Input:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
- Right -> Right -> Down -> Down
- Down -> Down -> Right -> Right
思路与解法
由题意可知,我们需要计算机器人从地图左上角位置走到地图右下角的所有可能的路径数量(避开障碍物,且每一步只能向下或者向右)。我将原点坐标设置为(1,1)
。
其中一种方法便是利用BFS广度优先搜索来模拟机器人所有可能行走的路径,知道当前位置为地图右下角时,路径数量加1。这种方法的时间复杂度为
O
(
M
N
)
O(MN)
O(MN)。
此外,动态规划也可以解决此题目:
我们要计算从(1,1)
到达(i,j)
位置的路径数量,即为从(1,1)
到达(i-1,j)
和从(1,1)
到达(i,j-1)
的路径数量之和。状态转移方程为:dp[i][j] = dp[i-1][j] + dp[i][j-1]
。
代码实现(Go)
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
rows := len(obstacleGrid)
cols := len(obstacleGrid[0])
dp := make([][]int, 0)
// dp数据初始化,默认为0
for i:=0; i<=rows; i++ {
row := make([]int, cols+1)
dp = append(dp, row)
}
// 机器人从(1,1)位置到达(1,1)位置路径数为1
dp[1][1] = 1
// 如果起点位置被障碍物所占用,则路径数为0
if obstacleGrid[0][0] == 1 {
dp[1][1] = 0
}
// 递推计算(1,1)到达(i,j)的路径数
for i:=1; i<=rows; i++ {
for j:=1; j<=cols; j++ {
if obstacleGrid[i-1][j-1] == 0 && !(i==1 && j==1) {
dp[i][j] = dp[i-1][j] + dp[i][j-1]
}
}
}
return dp[rows][cols]
}
遇到的问题
动态规划的难度主要在于状态转移方程,其次是dp数组的初始化。我们需要根据具体情况,对dp进行合理的初始化。在此题目中,一般情况下dp[1][1]=1
,这也符合我们的认知;另一方面,如果(1,1)为障碍物所占用,则说明机器人不存在,则dp[1][1]=0
。