题目描述
给你一个 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
解释:如图所示,为和最小的两条下降路径
思路
代码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& matrix) {
int n = matrix.size();
vector<vector<int>> dp(n, vector<int>(n));
copy(matrix[0].begin(), matrix[0].end(), dp[0].begin());//第一行每个元素的和最小下降路径长度为它们本身的值。
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {//边界情况,第一列和最后一列需要特殊处理
int mn = dp[i - 1][j];
if (j > 0) {
mn = min(mn, dp[i - 1][j - 1]);
}
if (j < n - 1) {
mn = min(mn, dp[i - 1][j + 1]);
}
dp[i][j] = mn + matrix[i][j];
}
}
return *min_element(dp[n - 1].begin(), dp[n - 1].end());
}
};
class Solution1 {
public:
int minFallingPathSum(vector<vector<int>>& matrix) {
int n = matrix.size();
vector<vector<int>> dp(n + 1, vector<int>(n + 2, 0));
// Base case
for (int i = 1; i <= n; i++) {
dp[i][0] = INT_MAX;//第一列特殊处理
dp[i][n + 1] = INT_MAX;//最后一列特殊处理
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = matrix[i - 1][j - 1] + min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j + 1]));
}
}
int ans = INT_MAX;
for (int i = 1; i <= n; i++) {
ans = min(ans, dp[n][i]);
}
return ans;
}
};
vector<int> split(string params_str) {
vector<int> p;
while (params_str.find(",") != string::npos) {
int found = params_str.find(",");
p.push_back(stoi(params_str.substr(0, found)));
params_str = params_str.substr(found + 1);
}
p.push_back(stoi(params_str));
return p;
}
vector<vector<int>> v;
vector<int> p;
vector<vector<int>> split_2_dimention(string s) {
s += " ";//防止最后一个]后面没有元素所导致的越界
while (s.find("]") != string::npos) {
int found_right = s.find("]");
string s1 = s.substr(1, found_right - 1);
p = split(s1);
v.push_back(p);
s = s.substr(found_right + 2);//取第二个vector,这里可能会越界
p.clear();
}
return v;
}
int main() {
string input;
getline(cin, input);//[[2,1,3],[6,5,4],[7,8,9]]
string input_str = input.substr(1, input.size() - 2);
vector<vector<int>> dp;
dp = split_2_dimention(input_str);
Solution a;
cout << a.minFallingPathSum(dp);
}
复杂度分析
时间复杂度:O(n2),需要计算每个坐标的和最小下降路径。
空间复杂度:O(n2),需要记录每个坐标的和最小下降路径。
因为每个坐标的和最小下降路径仅与上一行有关,因此可以使用滚动数组,使得空间复杂度降低为 O(n)。