题面

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?

类似我们做过的62. Unique Paths,给定矩阵,其中0-无障碍物, 1-有障碍物(无法通过),找出到达右下角的不重复的路径数。

样例

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:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right

2. Input
[[0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],[0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0],[1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,1],[0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0],[0,0,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0],[1,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0],[0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0],[0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],[1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0],[0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0],[0,1,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1],[1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,1,1],[0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,1],[1,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1],[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0]]
这个样例是做的过程中,遇到的一个棘手样例。int 会爆
Output : 1637984640

思路

我们采用和62. Unique Paths一样的思路,到达某点的路径数就是到达它的上边点和左边点路径数的和,只不过要注意的是,当有障碍物时,该点的路径数就要置0(无法到达该点)

算法(直接采用空间压缩DP算法)

时间复杂度:O(m*n)

空间复杂度:O(n)

1. 新建dp[n],预处理第一行(只能往右走,所以出现障碍物之后的点都无法到达置0, 之前的置1)

2. 遍历给定二位矩阵,第一列单独处理(没有左边的点),如果该点为1,即有障碍物,那么该点路径数置0;

3. 其他点正常处理,如果给定矩阵该点为1,即有障碍物,那么dp数组对应点置0;否则,该点路径加和左边点路径。

4. 返回dp末尾元素置。

源码

 1 class Solution {
 2 public:
 3     int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
 4         int row = obstacleGrid.size(), col = obstacleGrid[0].size();
 5         vector<unsigned int> dp(col, 0);//采用unsigned int 应对样例2的数据
 6         for(int i=0; i<col; i++)//第一行预处理
 7         {
 8             if(obstacleGrid[0][i] == 1)
 9                 break;
10             dp[i] = 1;
11         }
12         for(int i=1; i<row; i++)
13         {
14             if(obstacleGrid[i][0] == 1)//第一列特殊处理
15                 dp[0] = 0;
16             for(int j=1; j<col; j++)//处理其他元素
17             {
18                 if(obstacleGrid[i][j] == 1)//遇到障碍物,无法通过置0
19                     dp[j] = 0;
20                 else
21                     dp[j] += dp[j-1];//可以通过,加和左边点路径。
22             }
23         }
24         return dp[col-1];
25     }
26 };

注意

 这里用了一维DP数组来做,用二维DP也可以,结果差不多。

二维DP源码

和一维大同小异

时间复杂度:O(m*n)

空间复杂度:O(m*n)

 1 class Solution {
 2 public:
 3     int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
 4         int row = obstacleGrid.size(), col = obstacleGrid[0].size();
 5         vector<vector<unsigned int>> dp(row, vector<unsigned int>(col, 0));//二维vector你get了吗?
 6         for(int i=0; i<col; i++)
 7         {
 8             if(obstacleGrid[0][i] == 1)
 9                 break;
10             dp[0][i] = 1;
11         }
12         for(int i=0; i<row; i++)
13         {
14             if(obstacleGrid[i][0] == 1)
15                 break;
16             dp[i][0] = 1;
17         }
18         for(int i=1; i<row; i++)
19         {
20             for(int j=1; j<col; j++)
21             {
22                 if(obstacleGrid[i][j] == 1)
23                     dp[i][j] = 0;
24                 else
25                     dp[i][j] = dp[i][j-1] + dp[i-1][j];
26             }
27         }
28         return dp[row-1][col-1];
29     }
30 };