这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
前言
力扣第六十四题 最小路径和 如下所示:
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明: 每次只能向下或者向右移动一步。
示例 1:
输入: grid = [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
示例 2:
输入: grid = [[1,2,3],[4,5,6]]
输出: 12
一、思路
最小路径和 这一题和之前的 不同路径(六十三和六十四题)有很多相似的地方,有兴趣的可以看一下之前的题目。
最小路径和 中有两个比较重要的信息:
- 每次只能向下或向右移动一步
- 需要计算的值为:最小路径和
很显然这一题也可以使用动态规划来求解,既然需要计算最小路径和,我们就假设 dp[i][j] 为从 grid[0][0] 到 grid[i][j] 的最短路径和。
通过归纳可得状态转移方程为:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid (i>1, j>1)。因为要想到达 [i][j] 这个点只能从左边或者上边过来,所以从中取较小值即可。
对于二维数组 dp[][] 中的第一行 dp[0][] 来说,它只可能是从左至右的,所以可以通过 dp[0][i] = dp[0][i-1] + grid[0][i] (i > 1) 来填充第一行的值。至于第一列的话,填充的方式为从上至下。
综上所述,实现的步骤大致分为以下几步:
- 初始化第一行、第一列
- 遍历二维数组
dp[][]并根据状态转移方程填充值 - 返回右下角
dp[m-1][n-1]的值即可
举个例子
此处以示例中的 grid = [[1,3,1],[1,5,1],[4,2,1]] 作为例子
- 初始化
dp[][]的第一行,dp[0][] = [1, 4, 5] - 初始化
dp[][]的第一列,dp[][0] = [1, 2, 6] - 遍历从第二行开始,当
i=1时,根据状态转移方程,填充此行。dp[1][] = [2, 7, 6] - 当
i=2时,根据状态转移方程,填充此行。dp[2][] = [6, 8, 7] - 返回
dp[2][2]的值7即可
二、实现
实现代码
实现代码与思路中保持一致
/**
* 动态规划
*/
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<n; i++) {
dp[0][i] = dp[0][i-1] + grid[0][i];
}
for (int i=1; i<m; i++) {
dp[i][0] = dp[i-1][0] + grid[i][0];
}
// 遍历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];
}
测试代码
public static void main(String[] args) {
int[][] grid = {{1,3,1},{1,5,1},{4,2,1}};
new Number64().minPathSum(grid);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~