力扣第六十四题-最小路径和

287 阅读3分钟

这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战

前言

力扣第六十四题 最小路径和 如下所示:

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明: 每次只能向下或者向右移动一步。

示例 1:

输入: grid = [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
解释: 因为路径 13111 的总和最小。

示例 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) 来填充第一行的值。至于第一列的话,填充的方式为从上至下

综上所述,实现的步骤大致分为以下几步:

  1. 初始化第一行、第一列
  2. 遍历二维数组 dp[][] 并根据状态转移方程填充值
  3. 返回右下角 dp[m-1][n-1] 的值即可

举个例子

此处以示例中的 grid = [[1,3,1],[1,5,1],[4,2,1]] 作为例子

  1. 初始化 dp[][] 的第一行,dp[0][] = [1, 4, 5]
  2. 初始化 dp[][] 的第一列,dp[][0] = [1, 2, 6]
  3. 遍历从第二行开始,当 i=1 时,根据状态转移方程,填充此行。dp[1][] = [2, 7, 6]
  4. i=2 时,根据状态转移方程,填充此行。dp[2][] = [6, 8, 7]
  5. 返回 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);
    }

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~