不同路径 II
题目描述:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
示例说明请见LeetCode官网。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths-ii/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一:递归法
首先,经过分析可知,到达任意一个单元格子的最后一步,可以从这个格子的左边过来,也可以从这个格子的上边过来,所以到达任意一个格子的步数是到它左边的步数加上到它上面格子的步数之和,所以可以用递归的方法求解,具体过程如下:
- 如果m等于1或者n等于1,直接返回1;
- 如果上面的条件不满足,则递归调用该方法求解
uniquePaths(m - 1, n) + uniquePaths(m, n - 1)
。说明:和LeetCode-062-不同路径的区别在于,当左边或者上面的走法为0(即走不通的时候),则只用继续往一个方向递归。
解法二:迭代法
首先记录第一行的格子的走法columns,从第一个元素开始判断,如果第一个元素的值为1(即有障碍物),则为0,然后给columns的后面的元素赋值,赋值时需要同时判断前面一个元素的值和当前位置是否有障碍物。然后根据columns迭代获取下面每一行相应的走法,迭代过程如下:
- 首先根据上一行第一个元素的值和当前行第一个元素是否有障碍物获取columns[0]的值;
- 然后重复上面的过程,给columns的后面的元素赋值,赋值时需要同时判断前面一个元素的值和当前位置是否有障碍物。
最后返回columns最后一个元素的值即为最终的走法。
说明:解决过程类似 LeetCode-062-不同路径,特别注意当第一个元素为1时,则走不通;当只有一个元素时,且为0时,返回1也就是有一种走法,而不是返回0。
public class LeetCode_063 {
/**
* 递归法
*
* @param obstacleGrid
* @return
*/
public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length, n = obstacleGrid[0].length;
if (m == 1 && n == 1) {
if (obstacleGrid[m - 1][n - 1] == 1) {
return 0;
} else {
return 1;
}
}
if (obstacleGrid[m - 1][n - 1] == 1) {
return 0;
}
return uniquePathsWithObstacles(obstacleGrid, obstacleGrid.length - 1, obstacleGrid[0].length - 1);
}
private static int uniquePathsWithObstacles(int[][] obstacleGrid, int x, int y) {
if (obstacleGrid[x][y] == 1) {
return 0;
}
if (x == 0 && y == 0) {
if (obstacleGrid[x][y] == 1) {
return 0;
} else {
return 1;
}
}
if (x > 0) {
if (y > 0) {
if (obstacleGrid[x - 1][y] == 1) {
if (obstacleGrid[x][y - 1] == 1) {
return 0;
} else {
return uniquePathsWithObstacles(obstacleGrid, x, y - 1);
}
} else {
if (obstacleGrid[x][y - 1] == 1) {
return uniquePathsWithObstacles(obstacleGrid, x - 1, y);
} else {
return uniquePathsWithObstacles(obstacleGrid, x - 1, y) + uniquePathsWithObstacles(obstacleGrid, x, y - 1);
}
}
} else {
if (obstacleGrid[x - 1][y] == 1) {
return 0;
} else {
return uniquePathsWithObstacles(obstacleGrid, x - 1, y);
}
}
} else {
if (obstacleGrid[x][y - 1] == 1) {
return 0;
} else {
return uniquePathsWithObstacles(obstacleGrid, x, y - 1);
}
}
}
/**
* 迭代法
*
* @param obstacleGrid
* @return
*/
public static int uniquePathsWithObstacles2(int[][] obstacleGrid) {
int m = obstacleGrid.length, n = obstacleGrid[0].length;
int[] columns = new int[n];
if (obstacleGrid[0][0] == 1) {
columns[0] = 0;
} else {
columns[0] = 1;
}
// 初始化第一行
for (int i = 1; i < n; i++) {
if (columns[i - 1] == 0) {
columns[i] = 0;
continue;
}
if (obstacleGrid[0][i] == 1) {
columns[i] = 0;
} else {
columns[i] = 1;
}
}
// 迭代过程
for (int i = 1; i < m; i++) {
// 第一个值
if (columns[0] == 0) {
for(int x = 1; x < n; x++) {
if(obstacleGrid[i][x] == 1) {
columns[x] = 0;
} else {
columns[x] = columns[x - 1] + columns[x];
}
}
continue;
}
if (obstacleGrid[i][0] == 1) {
columns[0] = 0;
} else {
columns[0] = 1;
}
for (int j = 1; j < n; j++) {
if (obstacleGrid[i][j] == 1) {
columns[j] = 0;
} else {
columns[j] = columns[j] + columns[j - 1];
}
}
}
return columns[n - 1];
}
public static void main(String[] args) {
int[][] obstacleGrid = new int[][]{{0}, {1}};
System.out.println(uniquePathsWithObstacles(obstacleGrid));
System.out.println(uniquePathsWithObstacles2(obstacleGrid));
}
}
【每日寄语】 机会不会等你,错过以后可能不会再有。