https://oj.leetcode.com/problems/unique-paths-ii/
Follow up for "Unique Paths":
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.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[ [0,0,0], [0,1,0], [0,0,0] ]
The total number of unique paths is 2
.
Note: m and n will be at most 100.
解题思路:
这是一道带条件的dp。有了上一道题的基础,这题就比较简单了。注意几个不同点。
1. 判断的时候,不仅仅需要看obstacleGrid[i - 1][j]和obstacleGrid[i][j - 1],obstacleGrid[i][j]自己也需要考虑。一个为1的点,到不了自己。
2. 初始化的时候,不能将前一个点为0的点,就设置为1。应该是设置为前一个dp值。因为前面有1,直接就被挡掉了,无法到后面。其实也就是用下面的dp方法,不能粗想想都置为1了。
dp[i][j] = dp[i - 1][j] + dp[i][j - 1], if obstalcleGrid[i][j] == 0
= 0, if obstacleGrid[i][j] == 1
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[][] dp = new int[m][n]; //dp[m][n]表示到点a[m][n]的不同路径数量,默认值为0 if(obstacleGrid[0][0] == 0){ dp[0][0] = 1; } for(int i = 1; i < n; i++){ if(obstacleGrid[0][i - 1] == 0 && obstacleGrid[0][i] == 0){ dp[0][i] = dp[0][i - 1]; } } for(int i = 1; i < m; i++){ if(obstacleGrid[i - 1][0] == 0 && obstacleGrid[i][0] == 0){ dp[i][0] = dp[i - 1][0]; } } for(int i = 1; i < m; i++){ for(int j = 1; j < n; j++){ if(obstacleGrid[i - 1][j] == 1 && obstacleGrid[i][j - 1] == 0 && obstacleGrid[i][j] == 0){ dp[i][j] = dp[i][j - 1]; } if(obstacleGrid[i - 1][j] == 0 && obstacleGrid[i][j - 1] == 1 && obstacleGrid[i][j] == 0){ dp[i][j] = dp[i - 1][j]; } if(obstacleGrid[i - 1][j] == 0 && obstacleGrid[i][j - 1] == 0 && obstacleGrid[i][j] == 0){ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } } } return dp[m - 1][n - 1]; } }
上面的还是有些复杂,改为下面的
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[][] dp = new int[m][n]; //dp[m][n]表示到点a[m][n]的不同路径数量,默认值为0 if(obstacleGrid[0][0] == 0){ dp[0][0] = 1; } for(int i = 1; i < n; i++){ if(obstacleGrid[0][i] == 0){ dp[0][i] = dp[0][i - 1]; } } for(int i = 1; i < m; i++){ if(obstacleGrid[i][0] == 0){ dp[i][0] = dp[i - 1][0]; } } for(int i = 1; i < m; i++){ for(int j = 1; j < n; j++){ if(obstacleGrid[i][j] == 0){ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }else{ dp[i][j] = 0; } } } return dp[m - 1][n - 1]; } }
与上题类似,这里也可以用一维数组解决问题。需要注意后面的循环必须判断j == 0,即若为第一列,那么如果该格!=1,直接继承上一列的dp就可以了。
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[] dp = new int[n]; //dp[m][n]表示到点a[m][n]的不同路径数量,默认值为0 if(obstacleGrid[0][0] == 0){ dp[0] = 1; } for(int i = 1; i < n; i++){ if(obstacleGrid[0][i] == 0){ dp[i] = dp[i - 1]; } } for(int i = 1; i < m; i++){ for(int j = 0; j < n; j++){ if(obstacleGrid[i][j] == 0){ if(j > 0){ dp[j] = dp[j] + dp[j - 1]; }else{ dp[j] = dp[j]; } }else{ dp[j] = 0; } } } return dp[n - 1]; } }
针对第一行的初始化可以省去,仅仅初始化第一格即可。但是后面的外循环要从0开始。
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[] dp = new int[n]; //dp[m][n]表示到点a[m][n]的不同路径数量,默认值为0 if(obstacleGrid[0][0] == 0){ dp[0] = 1; } //初始化可省略 //for(int i = 1; i < n; i++){ // if(obstacleGrid[0][i] == 0){ // dp[i] = dp[i - 1]; // } //} for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ if(obstacleGrid[i][j] == 0){ if(j > 0){ dp[j] = dp[j] + dp[j - 1]; }else{ dp[j] = dp[j]; } }else{ dp[j] = 0; } } } return dp[n - 1]; } }