LeetCode — 最小路径和
LeetCode — 最小路径和
问题陈述
给定一个 mxn网格 用非负数填充,找到一条从左上角到右下角的路径,该路径最小化沿其路径的所有数字的总和。
笔记: 您只能在任何时间点向下或向右移动。
问题陈述取自: https://leetcode.com/problems/minimum-path-sum
示例 1:
Source: LeetCode
输入:网格 = [[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.length
- n == 网格[i].length
- 1 <= 米,n <= 200
- 0 <= 网格[i][j] <= 100
解释
蛮力方法
蛮力方法是生成从左上角到右下角的所有可能路径。我们计算所有这些路径的总和并找到最小值。该解决方案适用于小型阵列,但对于大型阵列会超时。
最优子结构
到达 (m, n) 的路径必须通过以下两个单元之一:(m - 1, n) 或 (m, n - 1)。到达(m,n)的最小成本可以计算为“两个单元格的最小值加上网格(m,n)”。
minimumCost(m, n) = min(minimumCost(m - 1, n), minimumCost(m, n - 1)) + grid(m, n) int minCost(int grid[R][C], int m, int n)
{
如果 (n < 0 || m < 0)
返回 INT_MAX;
否则如果 (m == 0 && n == 0)
返回网格[m][n];
别的
返回网格[m][n] +
分钟(
minCost(网格,m - 1,n),
minCost(网格,m,n - 1)
);
}
动态规划
使用递归方法求解上述最优子结构。但是,如果我们仔细观察,上述方法会一次又一次地计算相同的子问题。
我们可以避免使用动态规划方法重新计算相同的子问题。我们创建一个二维数组并以自下而上的方式解决问题。
让我们跳到算法以更好地理解它。
- 设置 m = grid.size()
n = 网格[0].size()
dp(m, 向量<int>(n))
- 循环 i = 0;我 < 米;我++
j = 0 的循环; j
如果我 == 0 && j == 0
- 设置 dp[i][j] = 网格[i][j]
否则如果我 == 0
- 设置 dp[i][j] = dp[i][j - 1] + grid[i][j]
否则如果 j == 0
- 设置 dp[i][j] = dp[i - 1][j] + grid[i][j]
别的
- 设置 dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
- 结束
- 返回 dp[m - 1][n - 1]
这种方法的时间复杂度是 O(N^2) ,空间复杂度为 O(M*N) .
让我们检查一下我们的算法 C++ , 戈朗 , 和 Javascript .
C++ 解决方案
类解决方案{
上市:
int minPathSum(向量<vector<int> >&网格){
int m = grid.size();
int n = grid[0].size();
向量<vector<int> > dp(m, 向量<int>(n));
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
如果(我 == 0 && j == 0){
dp[i][j] = 网格[i][j];
} 否则如果(我 == 0){
dp[i][j] = dp[i][j - 1] + 网格[i][j];
}否则如果(j == 0){
dp[i][j] = dp[i - 1][j] + 网格[i][j];
} 别的 {
dp[i][j] = min(dp[i- 1][j], dp[i][j - 1]) + 网格[i][j];
}
}
}
返回 dp[m - 1][n - 1];
}
};
Golang 解决方案
func minPathSum(grid [][]int) int {
m := 长度(网格)
n := len(grid[0])
dp := make([][]int, m)
对于 k := 范围 dp {
dp[k] = make([]int, n)
}
对于我:= 0;我 < 米;我++ {
对于 j := 0; j < n; j++ {
如果我 == 0 && j == 0 {
dp[i][j] = 网格[i][j]
} 否则如果我 == 0 {
dp[i][j] = dp[i][j - 1] + 网格[i][j]
} 否则如果 j == 0 {
dp[i][j] = dp[i - 1][j] + 网格[i][j]
} 别的 {
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + 网格[i][j]
}
}
}
返回 dp[m - 1][n - 1]
}
func min(a, b int) int {
如果 a < b {
返回一个
}
返回 b
}
Javascript 解决方案
var minPathSum = 函数(网格){
让 m = grid.length;
让 n = grid[0].length;
让 dp = 新数组(m);
for(让 k = 0; k < dp.length; k++) {
dp[k] = 新数组(n);
}
for(让 i = 0; i < m; i++) {
for(让 j = 0; j < n; j++) {
如果(我 == 0 && j == 0){
dp[i][j] = 网格[i][j];
} 否则如果(我 == 0){
dp[i][j] = dp[i][j - 1] + 网格[i][j];
}否则如果(j == 0){
dp[i][j] = dp[i - 1][j] + 网格[i][j];
} 别的 {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
}
返回 dp[m - 1][n - 1];
};
让我们空运行我们的算法 示例 2 .
输入:grid = [[1, 2, 3], [4, 5, 6]]
第 1 步:m = grid.size()
= 2
n = 网格[0].size()
= 3
dp(2, 3)
第 2 步:循环 i = 0;我 < 米
0 < 2
真的
j = 0 的循环; j < n
0 < 3
真的
如果我 == 0 && j == 0
真的
dp[i][j] = 网格[i][j]
= 网格[0][0]
= 1
dp = [[1, 0, 0], [0, 0, 0]]
j++
j = 1
j < n
1 < 3
真的
如果我 == 0 && j == 0
真的
否则如果我 == 0
真的
dp[i][j] = dp[i][j - 1] + 网格[i][j]
= dp[0][1 - 1] + 网格[0][1]
= dp[0][0] + 网格[0][1]
= 1 + 2
= 3
dp = [[1, 3, 0], [0, 0, 0]]
j++
j < n
2 < 3
真的
如果我 == 0 && j == 0
真的
否则如果我 == 0
真的
dp[i][j] = dp[i][j - 1] + 网格[i][j]
= dp[0][2 - 1] + 网格[0][1]
= dp[0][1] + 网格[0][2]
= 3 + 3
= 6
dp = [[1, 3, 6], [0, 0, 0]]
j++
j < n
3 < 3
错误的
我++
我 = 1
第 3 步:循环 i < m
1 < 2
真的
j = 0 的循环; j < n
0 < 3
真的
如果我 == 0 && j == 0
错误的
否则如果我 == 0
错误的
否则如果 j == 0
真的
dp[i][j] = dp[i - 1][j] + 网格[i][j]
= dp[1 - 1][0] + 网格[1][0]
= dp[0][0] + 网格[1][0]
= 1 + 4
= 5
dp = [[1, 3, 6], [5, 0, 0]]
j++
j < n
1 < 3
真的
如果我 == 0 && j == 0
错误的
否则如果我 == 0
错误的
否则如果 j == 0
错误的
别的
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + 网格[i][j]
= min(dp[1][1 - 1], dp[1 - 1][1]) + 网格[1][1]
= min(dp[1][0], dp[0][1]) + 5
= min(5, 3) + 5
= 3 + 5
= 8
dp = [[1, 3, 6], [5, 8, 0]]
j++
j < n
2 < 3
真的
如果我 == 0 && j == 0
错误的
否则如果我 == 0
错误的
否则如果 j == 0
错误的
别的
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + 网格[i][j]
= min(dp[1][2 - 1], dp[1 - 1][2]) + 网格[1][2]
= min(dp[1][1], dp[0][2]) + 6
= min(8, 6) + 6
= 6 + 6
= 12
dp = [[1, 3, 6], [5, 8, 12]]
j++
j < n
3 < 3
错误的
我++
我 = 2
第 4 步:循环 i < m
2 < 2
错误的
第 5 步:返回 dp[m - 1][n - 1]
dp[2 - 1][3 - 1]
dp[1][2]
12
我们将答案返回为 12。
最初发表于 https://alkeshghorpade.me .
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明