62. Unique Paths
问题
A robot is located at the top-left corner of a m × 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).
How many possible unique paths are there?
Above is a 3 × 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
思路
- 让左上角的起点格子坐标为(0,0)。
- 当只有一个格子时,只有一种走法。
- 当只有一行或只有一列格子时,走法也是1。
- 当有多行多列格子时,由于只能往右或往下走,所以对于一个给定的格子,来到这个格子的方法只能是从左边过来或从上边下来。所以来到这个格子的方法数等于左边格子的方法数加上上边格子的方法数。即
uniquePaths(m, n) = uniquePaths(m - 1, n) + uniquePaths(m, n - 1)
。
+----+----+----+----+----+----+----+----+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+----+----+----+----+----+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+----+----+----+----+----+----+----+----+
| 1 | 3 | 6 | 10 | 15 | 21 | 28 | 36 |
+----+----+----+----+----+----+----+----+
| 1 | 4 | 10 | 20 | 35 | 56 | 84 |120 |
+----+----+----+----+----+----+----+----+
- 起始状态:最左边一列和最上边一行的步数都是1
代码
public class UniquePaths {
public int uniquePaths(int m, int n) {
if (m == 0 || n == 0)
return 1;
int[][] paths = new int[m][n]; // 存储每个格子的步数
for (int i = 0; i < m; i++) {
paths[i][0] = 1; // 最左边一列设置为1
}
for (int i = 0; i < n; i++) {
paths[0][i] = 1; // 最上边一行设置为1
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
paths[i][j] = paths[i - 1][j] + paths[i][j - 1]; // 左边步数加上上边步数
}
}
return paths[m - 1][n - 1]; // 返回最后一个元素
}
}
63. 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数组的行和列时,遇到障碍物了,之后全部都设置为0。
- 递归过程中,遇到障碍物,将此位置设置为0即可
代码
public class UniquePaths_II {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int line = obstacleGrid.length; // 行数
int row = obstacleGrid[0].length; // 列数
int[][] paths = new int[line][row];
for (int i = 0; i < row; i++) { // 第一行 注意,一旦遇到有障碍,这一行后面所有全部设置为0
if (obstacleGrid[0][i] == 1) {
while (i < row) {
paths[0][i] = 0;
i++;
}
} else
paths[0][i] = 1;
}
for (int i = 0; i < line; i++) { // 第一列 一旦遇到障碍,这一列剩余所有全部设置为0
if (obstacleGrid[i][0] == 1) {
while (i < line) {
paths[i][0] = 0;
i++;
}
} else
paths[i][0] = 1;
}
for (int i = 1; i < line; i++) {
for (int j = 1; j < row; j++) {
if (obstacleGrid[i][j] != 1) {
paths[i][j] = paths[i - 1][j] + paths[i][j - 1];
} else {
paths[i][j] = 0;
}
}
}
return paths[line - 1][row - 1];
}
}
64. Minimum Path Sum
问题
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
思路
基本思路与第一题一样。给定的格子带有自己的步数,要求最短步数,就把给定格子自己的步数加上左边和上边格子中步数较小的一个。
初始化:
1. 左上角设置为给定网格的第一个格子里的数。
2. 第一行和第一列,设置为此格子自己的步数加上前一个格子的步数。
代码
public class MinimumPathSum {
public int minPathSum(int[][] grid){
int row = grid[0].length;
int line = grid.length;
int[][] dp = new int[line][row];
dp[0][0]=grid[0][0]; // 左上角设置为给定网格的第一个格子里的数
for(int i=1;i<line;i++){ // 初始化第一行
dp[i][0]=grid[i][0]+dp[i-1][0];
}
for(int i=1;i<row;i++){ // 初始化第一列
dp[0][i]=grid[0][i]+dp[0][i-1];
}
for(int i=1;i<line;i++){ // 递归
for(int j=1;j<row;j++){
// 定格子自己的步数加上左边和上边格子中步数较小的一个
dp[i][j]=Math.min(dp[i-1][j], dp[i][j-1])+grid[i][j];
}
}
return dp[line-1][row-1];
}
}