0%

『LeetCode』931 下降路径最小和

题目

931. 下降路径最小和

给你一个 n x n方形 整数数组 matrix ,请你找出并返回通过 matrix下降路径最小和

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)(row + 1, col) 或者 (row + 1, col + 1)

示例 1:

输入:matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出:13
解释:如图所示,为和最小的两条下降路径

示例 2:

输入:matrix = [[-19,57],[-40,-5]]
输出:-59
解释:如图所示,为和最小的下降路径

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 100
  • -100 <= matrix[i][j] <= 100

标签

数组, 动态规划, 矩阵


题解

【下降路径最小和】动态规划

动态规划

不能想到,该问题具有无后效性,适合用动态规划,具体来说,第 \(i\) 行的结果只取决于第 \(i - 1\) 行而不用考虑第 \(i - 1\) 行之前的路径。

据此还可以使用滚动数组进行优化

1
2
3
4
5
6
7
8
9
# Code language: Python
class Solution:
def minFallingPathSum(self, matrix: List[List[int]]) -> int:
n, m = len(matrix), len(matrix[0])
# 原地修改
for i in range(1, n):
for j in range(m):
matrix[i][j] += min(matrix[i - 1][j], (matrix[i - 1][j - 1] if j > 0 else float('inf')), (matrix[i - 1][j + 1] if j + 1 < m else float('inf')))
return min(matrix[-1])
1
2
3
4
5
6
7
8
9
10
# Code language: Python
class Solution:
def minFallingPathSum(self, matrix: List[List[int]]) -> int:
n, m = len(matrix), len(matrix[0])
# 滚动数组
dp = matrix[0]
for i in range(1, n):
dp = [min(dp[j], (dp[j - 1] if j > 0 else float('inf')), (dp[j + 1] if j + 1 < m else float('inf'))) + matrix[i][j] for j in range(m)]

return min(dp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Code language: Java
class Solution {
public int minFallingPathSum(int[][] matrix) {
int n = matrix.length;
int[][] dp = new int[n][n + 2];
for (int[] s : dp)
Arrays.fill(s, 0x3f3f3f3f);

for (int i = 0; i < n; ++i) {
dp[0][i + 1] = matrix[0][i];
}

for (int i = 1; i < n; ++i) {
for (int j = 0; j < n; ++j) {
dp[i][j + 1] = matrix[i][j] + Math.min(dp[i - 1][j], Math.min(dp[i - 1][j + 1], dp[i - 1][j + 2]));
}
}

int ans = dp[n - 1][0];
for (int s : dp[n - 1])
ans = Math.min(ans, s);
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Code language: C++
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& matrix) {
int n = matrix.size(), m = matrix[0].size();
// 原地修改
for (int i = 1; i < n; ++i) {
for (int j = 0; j < m; ++j) {
matrix[i][j] += min(matrix[i - 1][j], min(j > 0 ? matrix[i - 1][j - 1] : INT_MAX, j + 1 < m ? matrix[i - 1][j + 1] : INT_MAX));
}
}
int ans = INT_MAX;
for (int i = 0; i < m; ++i) ans = min(ans, matrix[n - 1][i]);
return ans;
}
};
  • 时间复杂度: \(O(nm)\)
  • 空间复杂度: \(O(1)\) - 原地修改,\(O(m)\) - 滚动数组,\(O(nm)\) - 无优化

如果对你有帮助的话,请给我点个赞吧~

欢迎前往 我的博客Algorithm - Github 查看更多题解

--- ♥ end ♥ ---

欢迎关注我呀~