一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 17 天,点击查看活动详情。
最小路径和
给定一个包含非负整数的 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
提示:
m == grid.lengthn == grid[i].length1 <= m,n <= 2000 <= grid[i][j] <= 100
思路分析
- 定义一个
res数组,其中res[i][j]表示从左上角走到(i, j)的最小路径; - 题目规定,只能向右或者向下移动,因此想要走到
(i, j),如果向下走一步到达,就是从(i-1, j)走过来;若向右走一步到达,就是从(i, j-1)走过来; - 按照2得出,
res[i][j] += Math.min(res[i-1][j], res[i][j-1]); - 然后来确定初值,若
m或者n有一个为0,则都只有一条路径可以到达,到达的最短路径也就是在这条线上的各个节点之和,那对于剩余的节点来说,res中的值都为grid中对应位置的值,这样可以确保计算的时候,加上了自身的节点数,当然也可以使用grid[i][j]来替代; - 按照步骤三的公式,最终计算得到
res。
AC 代码
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function(grid) {
const m = grid.length
const n = grid[0].length
const res = grid
let tempM = 0, tempN = 0
for (let i = 0; i < m; i++) {
tempM += grid[i][0]
res[i][0] = tempM
}
for (let j = 0; j < n; j++) {
tempN += grid[0][j]
res[0][j] = tempN
}
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
res[i][j] += Math.min(res[i][j - 1],res[i-1][j])
}
}
return res[m - 1][n - 1]
};
结果:
- 执行结果: 通过
- 执行用时:272 ms, 在所有 JavaScript 提交中击败了6.21%的用户
- 内存消耗:49.9 MB, 在所有 JavaScript 提交中击败了5.02%的用户
- 通过测试用例:61 / 61
总结
上篇文章中写了,从左上角到右下角的路径总数,因此看到这个题目的第一想法就是,在所有的路径中找到最小的数字总和。在改造的过程中,首先是要确定 res 的初值,这决定后续节点的计算。
定义了两个临时变量,在计算在第一行和第一列中各个节点的路径和。在后续处理的过程中,因为给 res 赋的初值每个节点上都为 0,因此在使用公式计算时,会出错。在排查后才得到了正确的答案。
虽然不是一个最佳的答案,但是也是从上一题衍生后,一步一步踩坑得出来的结果。