LeetCode 64最小路径和
-
题目简述:给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
-
输入:
[ 1 3 1 1 5 1 4 2 1 ] \left[\begin{matrix}1 & 3 & 1 \\1 & 5 & 1 \\4 & 2 & 1\end{matrix} \right] ⎣⎡114352111⎦⎤
输出:7 解释:路径 1→3→1→1→1 的总和最小 -
思路:动态规划
O(nm)
-
状态表示:
f[i][j]
表示从起点走到点[i,j]
的路径和 -
状态属性:所有路径和中的最小值
-
状态转移:只能向右或者向下走,即当前单元格
[i,j]
只能从左边的单元格[i-1,j]
或者上方的单元格[i,j-1]
转移而来。走到当前单元格
[i,j]
的最小路径和=
“从左方单元格[i-1,j]
与 从上方单元格[i,j-1]
走来的 两个最小路径和中较小的 ”+
当前单元格值grid[i][j]
。- 当左边和上边都不是矩阵边界时:
f[i][j] = min(f[i-1][j], f[i][j-1]) + grid[i][j]
- 当只有左边界是矩阵边界时:只能从上边来,
f[i][j] = f[i][j - 1] + grid[i][j]
- 当只有上边界时矩阵边界时:只能从左边来,
f[i][j] = f[i - 1][j] + grid[i][j]
- 当左边和上边都是矩阵边界时:就是起点,
f[i][j] = grid[i][j]
- 当左边和上边都不是矩阵边界时:
-
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
vector<vector<int>> f(n, vector<int> (m, 0));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
{
if(i == 0 && j == 0) f[i][j] = grid[i][j];
else if(i == 0 && j > 0) f[i][j] = f[i][j - 1] + grid[i][j];
else if(j == 0 && i > 0) f[i][j] = f[i - 1][j] + grid[i][j];
else f[i][j] = min(f[i - 1][j], f[i][j - 1]) + grid[i][j];
}
return f[n - 1][m - 1];
}
};
- 思路:二维数组优化成一维数组
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
vector<int> f(m + 1, INT_MAX);
f[1] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
f[j] = min(f[j - 1], f[j]) + grid[i - 1][j - 1];
}
return f[m];
}
};