思路:
还是一样,先使用递归来接,无非是向右和向下,然后得到两种方式进行比较,代码如下:
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];}