题目在这->63. 不同路径 II - 力扣(LeetCode)
给定一个 m x n
的整数数组 grid
。一个机器人初始位于 左上角(即 grid[0][0]
)。机器人尝试移动到 右下角(即 grid[m - 1][n - 1]
)。机器人每次只能向下或者向右移动一步。
网格中的障碍物和空位置分别用 1
和 0
来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。
返回机器人能够到达右下角的不同路径数量。
测试用例保证答案小于等于 2 * 109
。
示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2
条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
示例 2:
输入:obstacleGrid = [[0,1],[0,0]] 输出:1
提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j]
为0
或1
该题还是属于二维数组的动态规划问题。由62. 不同路径 - 力扣(LeetCode)该题可知,grid[i][j]表示到达(i,j)该位置的路线有几种。因为只能向右或向下移动。所以,该二维数组的第一行只能是从左边过来的,第一列只能是从上边过来的。所以可以初始化二维数组的第一行和第一列,使grid[i][0]和gride[0][j]都为1,只有一条路线,然后让其他位置的路线数就等于从它左边过来的路线加上从它上边过来的路线,即grid[i][j] = grid[i - 1][j] + grid[i][j - 1](0 < i < n,0 < j < m)。
然后这题和由于多了一个障碍物,所以我起初的想法是在上面一题的基础上多加几个判断。
具体代码如下:
int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize) {
if (obstacleGrid[obstacleGridSize - 1][*obstacleGridColSize - 1] || obstacleGrid[0][0])
return 0;
obstacleGrid[0][0] = -1;
int flag = 0;
for (int i = 1;i < obstacleGridSize;i++)
{
if (obstacleGrid[i][0])
{
flag = 1;
}
else
{
if (!flag && obstacleGrid[i][0] == 0)
{
obstacleGrid[i][0] = -1;
}
}
}
flag = 0;
for (int j = 1;j < *obstacleGridColSize;j++)
{
if (obstacleGrid[0][j])
{
flag = 1;
}
else
{
if (!flag && obstacleGrid[0][j] == 0)
{
obstacleGrid[0][j] = -1;
}
}
}
for (int i = 1;i < obstacleGridSize;i++)
{
for (int j = 1;j < *obstacleGridColSize;j++)
{
if (obstacleGrid[i][j] != 1)
{
if (obstacleGrid[i][j - 1] < 0)
obstacleGrid[i][j] += obstacleGrid[i][j - 1];
if (obstacleGrid[i - 1][j] < 0)
obstacleGrid[i][j] += obstacleGrid[i - 1][j];
}
}
}
return -obstacleGrid[obstacleGridSize - 1][*obstacleGridColSize - 1];
}
我原以为就这样结束了,但是在我看完官方题解后发现了一种更为方便的方法---滚动数组。是一种针对于二维数组的滚动方法,根本不需要我上面写的那么麻烦。以下是我对官解中滚动数组的理解。
首先定义一个滚动数组f[m],给其一个初始化状态来记录每一行的到达每个位置的不同路径数。因为从一个位置出发一直向下走他的路径是不变的,只有从左边过来的,才是不同的路径,所以f[n]可以从同一列一直继承下去,反之也成立。由此便可以得到状态转移方程。
具体代码如下:
int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize) {
int n = obstacleGridSize,m = *obstacleGridColSize;
int f[m];
memset(f,0,sizeof(f));
f[0] = !obstacleGrid[0][0];
for (int i = 0;i < n;i++)
{
for (int j = 0;j < m;j++)
{
if (obstacleGrid[i][j] == 1)
f[j] = 0;
else
{
if (j - 1 >= 0 && obstacleGrid[i][j - 1] == 0)
{
f[j] += f[j - 1];
}
}
}
}
return f[m - 1];
}