LeetCode 64.最小路径和(中等)_最小值

题目描述

LeetCode 64.最小路径和(中等)_最小值_02


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

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

LeetCode 64.最小路径和(中等)_最小值

示例 1

LeetCode 64.最小路径和(中等)_最小值_02


LeetCode 64.最小路径和(中等)_最优路径_05



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

LeetCode 64.最小路径和(中等)_最小值

示例 2

LeetCode 64.最小路径和(中等)_最小值_02


输入:grid = [[1,2,3],[4,5,6]]
输出:12

LeetCode 64.最小路径和(中等)_最小值

提示

LeetCode 64.最小路径和(中等)_最小值_02


  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j] <= 100

LeetCode 64.最小路径和(中等)_最小值

题目分析

LeetCode 64.最小路径和(中等)_最小值_02


这道题我们可以通过定义一个同样大小的矩阵 ​​dp​​​ 来解决,其中的 ​​dp[i][j]​​​ 表示的是从左上角开始到 ​​(i, j)​​​ 位置的最优路径的累计值。因为每次只能向下或者向右移动,所以状态转移方程为 ​​dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]​​​ ,特别注意边界情况即可。(见题解一)累加的方法类似于 ​​LeetCode 304. 二维区域和检索 - 矩阵不可变​​​ 。当然,我们还能对空间进行压缩,因为 ​​dp​​​ 矩阵的每一个值只和左边和上面的值相关,我们可以使用空间压缩将 ​​dp​​​ 数组压缩为一维。对于第 ​​i​​​ 行,在遍历到第 ​​j​​​ 列的时候,因为第 ​​j-1​​​ 列已经更新过了,所以 ​​dp[j-1]​​​ 代表 ​​dp[i][j-1]​​​ 的值;而 ​​dp[j]​​​ 待更新,当前存储的值是在第 ​​i-1​​​ 行的时候计算的,所以代表 ​​dp[i-1][j]​​ 的值。(见题解二)

LeetCode 64.最小路径和(中等)_最小值

题解一

LeetCode 64.最小路径和(中等)_最小值_02


执行用时: 2 ms

内存消耗: 44.3 MB

class Solution {
public int minPathSum(int[][] grid) {
// 获取矩阵大小
int m = grid.length;
int n = grid[0].length;
// 定义 dp 矩阵
int[][] dp = new int[m][n];
// 遍历原矩阵
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
// 当遍历到第一个位置时
// 路径累计值等于该位置路径值
if (i == 0 && j == 0) {
dp[i][j] = grid[i][j];
} else if (i == 0) {
// i = 0 的边界情况
// 路径只能从 j - 1 通过
dp[i][j] = dp[i][j - 1] + grid[i][j];
} else if (j == 0) {
// j = 0 的边界情况
// 路径只能从 i - 1 通过
dp[i][j] = dp[i - 1][j] + grid[i][j];
} else {
// 普通情况取左边或上边累加的最小值加上当前位置的路径值
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
}
return dp[m - 1][n - 1];
}
}

LeetCode 64.最小路径和(中等)_最小值

题解二

LeetCode 64.最小路径和(中等)_最小值_02


执行用时: 2 ms

内存消耗: 43.8 MB

class Solution {
public int minPathSum(int[][] grid) {
// 获取矩阵大小
int m = grid.length;
int n = grid[0].length;
// 定义 dp 数组
int[] dp = new int[n];
// 遍历原矩阵
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
// 当遍历到第一个位置时
// 路径累计值等于该位置路径值
if (i == 0 && j == 0) {
dp[j] = grid[i][j];
} else if (i == 0) {
// i = 0 的边界情况
dp[j] = dp[j - 1] + grid[i][j];
} else if (j == 0) {
// j = 0 的边界情况
dp[j] = dp[j] + grid[i][j];
} else {
// 普通情况取左边或上边累加的最小值加上当前位置的路径值
dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j];
}
}
}
return dp[n - 1];
}
}

题目来源:力扣(LeetCode)