LeetCode刷题第5天之《64 最小路径和》

LeetCode 64 最小路径和

题目描述

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

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

示例

输入:[[1, 3, 1], [1, 5, 1], [4, 2, 1]]

输出:7

解释:1->3->1->1->1的总和最小为7

题目解析

有了求三角形最短路径和的经验,该题求在长方体中的最短路径和的思路也是类似的。也是采用动态规划的思想,将问题划分为更小规模的问题进行求解。具体思路如下:

  1. 既然是采用动态规划的方式求解,首先要做的就是找出其递推方程,下面先使用图示来模拟出程序可能出现的每一个结果,以此推导出我们要的递推方程。

    • 创建一个dp[n]的数组,用来保存每一行中到达每一个格子的最短路径。这里没有创建一个和输入一样大小的二维数组同样是使用到了“滚动数组”的概念,即重复的对该数组的值重新赋值。

    • 计算第一行每一个格子的数据。由于第一行中的格子只能由其右边格子走到,因此计算结果如下:用dp数组中数据来替换格子中的数据,此时dp = {1, 4, 5};

题解过程1

  • 计算接下去中每个格子的数据,其中由于第一格子的路径和只能由其上面格子的得到,因此可以提前计算出来,即是累加起来

题解过程2

对于接下去的格子,它可能是由其左边和上边格子得来,这个时候就要比较这两种走法路径和哪个最下了。如下:可以结合上图来看。

题解过程3

其最短路径路线即如下图:

示例图示

上述每一行的数据变化都是指dp数组中数据的变化。

  • 通过模拟一遍就可以发现地递推的一个过程了

    首先,第一行中的数据可以采用如下递推式:

    dp[i] = dp[i - 1] + grid[0] [j];

    接着,下面每一行的第一数据可以采用如下递推式:

    dp[0] = dp[0] + grid[i] [0];

    其他格子的递推式如下:

    dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j];
    

    最后将dp[n - 1]返回即是我们想要的答案。

程序实现

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[] dp = new int[n];
        dp[0] = grid[0][0];
        for (int i = 1; i < n; i++) {
            dp[i] = grid[0][i] + dp[i - 1];
        }
        for (int i = 1; i < m; i++) {
            dp[0] = dp[0] + grid[i][0];
            for (int j = 1; j < n; j++) {
                dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j];
            }
        }
        return dp[n - 1];
    }
}

程序运行结果

程序运行结果

时间复杂度为:O(n^2)

空间复杂度为:O(n)

PS: 不知是有了一些写动态规划题目的经验还是题目比较简单,现在看到类似的题目不再像以前看到动态规划的名称就发慌,不管怎么样还是得多练咯~

猜你喜欢

转载自blog.csdn.net/weixin_44184990/article/details/108581161