思路:
还是一样,先使用递归来接,无非是向右和向下,然后得到两种方式进行比较,代码如下:
public int minPathSum(int[][] grid) {
return calculate(grid, 0, 0);
}
private int calculate(int[][] grid, int i, int j) {
int m = grid.length;
int n = grid[0].length;
// 到达右下角
if (i == m - 1 && j == n - 1) {
return grid[i][j];
}
// 向下移动
int down = Integer.MAX_VALUE;
if (i < m - 1) {
down = calculate(grid, i + 1, j);
}
// 向右移动
int right = Integer.MAX_VALUE;
if (j < n - 1) {
right = calculate(grid, i, j + 1);
}
// 返回当前位置的值加上从当前位置向下或向右走的最小值
return grid[i][j] + Math.min(down, right);
}
然后依据此来改动态规划:
使用动态规划(DP)解决问题是处理此类网格路径问题的更有效方法。在这种情况下,我们会创建一个与原网格同样大小的 dp
数组,其中 dp[i][j]
表示从左上角到位置 (i, j)
的最小路径和。
动态规划的思路:
- 状态定义:定义
dp[i][j]
为从起点(0, 0)
到点(i, j)
的最小路径和。 - 初始化:
dp[0][0]
应初始化为grid[0][0]
,因为它是起始点。- 第一行和第一列的每个点都只能从它左边或上边的点到达,因此可以直接累加。
- 状态转移方程:
- 对于网格中的每个点
(i, j)
,dp[i][j]
可以从上方(i-1, j)
或左方(i, j-1)
到达,因此dp[i][j]
应为grid[i][j] + min(dp[i-1][j], dp[i][j-1])
。
- 对于网格中的每个点
- 计算顺序:从左到右,从上到下依次计算。
代码如下:
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
// 初始化起点
dp[0][0] = grid[0][0];
// 初始化第一列
for (int i = 1; i < m; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
// 初始化第一行
for (int j = 1; j < n; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
// 填充剩余的dp表
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
// 返回右下角的值
return dp[m - 1][n - 1];
}