@author: sdubrz
@date: 2020.04.17
题号: 64
题目难度: 中等
考察内容: 动态规划
原题链接 https://leetcode-cn.com/problems/minimum-path-sum/
题目的著作权归领扣网络所有,商业转载请联系官方授权,非商业转载请注明出处。
解题代码转载请联系 lwyz521604#163.com
给定一个包含非负整数的 m x n
网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明: 每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
通过次数77,450 提交次数118,548
动态规划解法
使用动态规划的关键是寻找最优子结构。从起始位置出发,到第 m 行的元素必须经过第 m-1 行。因而要计算从初始位置到第 m 行中的元素的最小代价可以先计算到第 m-1 行中的元素的最小代价。
这样,这个问题的子结构就可以基本确定下来了。我们需要计算在已知前 i 行元素的情况下,从初始位置到第 i 行中的元素的代价。对于第 i 行中的第 j 个元素,到达它有两种途径:
- 从第 i 行、第 j-1 个元素到达
- 从第 i-1 行、第 j 个元素到达
我们需要挑选这两种途径中代价较小的那个。
我们每次读取矩阵的一行,计算从初始位置到当前行中元素的最小代价。由于在计算到第 i 行中元素的最小代价时,只需要查看到第 i-1 行元素的代价以及第 i 行中的元素本身,因而,在迭代的过程中,我们不需要再去更新前面的 i-2 行元素的代价。
下面是具体的代码实现:
class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
if(m==0){
return 0;
}
int n = grid[0].length;
if(n==0){
return 0;
}
for(int i=1; i<n; i++){
grid[0][i] = grid[0][i] + grid[0][i-1];
}
for(int i=1; i<m; i++){
grid[i][0] = grid[i-1][0] + grid[i][0];
for(int j=1; j<n; j++){
int s1 = grid[i][j] + grid[i][j-1];
int s2 = grid[i][j] + grid[i-1][j];
grid[i][j] = Math.min(s1, s2);
}
}
return grid[m-1][n-1];
}
}
在 LeetCode 系统中提交的结果如下所示
执行结果: 通过 显示详情
执行用时 : 3 ms, 在所有 Java 提交中击败了 89.15% 的用户
内存消耗 : 42.6 MB, 在所有 Java 提交中击败了 24.24% 的用户
图论方法
这个问题应该也可以通过构造一个有向图,然后用 Dijkstra 算法来求解。不过那种方法应该不会比动态规划的方法简单快捷。