题目描述
给定一个方形整数数组 A
,我们想要得到通过 A
的_下降路径_的最小和。
下降路径可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列。
样例
输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:12
解释:
可能的下降路径有:
[1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9]
[2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9]
[3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9]
和最小的下降路径是 [1,4,7],所以答案是 12。
注意
1 <= A.length == A[0].length <= 100
-100 <= A[i][j] <= 100
。
算法
(动态规划) $O(nm)$
- $f(i, j)$ 表示到达第 $i$ 行第 $j$ 列的时候的最小值。
- 转移时有三种方式,分别是从第 $i-1$ 层的第 $j-1$,$j$ 和 $j+1$ 列到达第 $i$ 层,即 $f(i,j) = min(f(i - 1, j - 1), f(i - 1, j), f(i - 1, j + 1)) + a(i, j)$。
- 初始值 $f(0, j) = A(0, j)$,最终答案为 $\max_{j=0}^{m-1}{f(n-1, j)}$。
时间复杂度
- 状态数为 $nm$ 个,转移数为 3 个,故总时间复杂度为 $O(nm)$。
C++ 代码
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& A) {
int n = A.size(), m = A[0].size();
vector<vector<int>> f(n, vector<int>(m, 100000));
for (int j = 0; j < m; j++)
f[0][j] = A[0][j];
for (int i = 1; i < n; i++)
for (int j = 0; j < m; j++) {
f[i][j] = f[i - 1][j] + A[i][j];
if (j > 0)
f[i][j] = min(f[i][j], f[i - 1][j - 1] + A[i][j]);
if (j < m - 1)
f[i][j] = min(f[i][j], f[i - 1][j + 1] + A[i][j]);
}
int ans = 100000;
for (int j = 0; j < m; j++)
ans = min(ans, f[n - 1][j]);
return ans;
}
};
谢谢 wzc大佬!
补充一个压缩后的写法~