?题目描述
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
?Method 1: DP
class Solution {
public:
// [[2], [[2],
// [3,4], [5,6],
// [6,5,7], [11,10,11],
// [4,1,8,3]] [15,11,18,14]]
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
// ans_[i][j] = minTotalOf(i,j)
// ans_[i][j] = min(ans_[i-1][j],ans_[i-1][j-1]) + triange[i-1][j-1]
// ↓为了好操作,给二维数组加个padding 从1->n,所以 ans_[i][j]对应triange[i-1][j-1]
ans_ = vector<vector<int>>(n + 1, vector<int>(n + 1, INT32_MAX));//因为要求最小的total所以就设置成最大值,也就是边界
for (int i = 1; i <= n ; ++i) {
for (int j = 1; j <= i; ++j) {
ans_[i][j] = triangle[i-1][j-1];
if (i == 1) continue;
else if (j == 1) ans_[i][j] += ans_[i - 1][j];
else if (j == i) ans_[i][j] += ans_[i - 1][j - 1];
else ans_[i][j] += min(ans_[i - 1][j], ans_[i - 1][j - 1]);
}
}
return *min_element(ans_[n].begin(), ans_[n].end());
}
private:
vector<vector<int>> ans_;
};
?Method 2: DP,因为发现每次只会访问上一行元素,所以没有必要保留这么多行,只需要保留两行就行了,也就是滚动数组(swap使用)。
class Solution {
public:
// [[2], [[2],
// [3,4], [5,6],
// [6,5,7], [11,10,11],
// [4,1,8,3]] [15,11,18,14]]
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
// ans_[i][j] = minTotalOf(i,j)
// ans_[i][j] = min(ans_[i-1][j],ans_[i-1][j-1]) + triange[i-1][j-1]
// ↓为了好操作,给二维数组加个padding 从1->n,所以 ans_[i][j]对应triange[i-1][j-1]
ans_ = vector<vector<int>>(2, vector<int>(n + 1, INT32_MAX));//因为要求最小的total所以就设置成最大值,也就是边界
for (int i = 1; i <= n ; ++i) {
for (int j = 1; j <= i; ++j) {
ans_[1][j] = triangle[i-1][j-1];
if (i == 1 && j == 1) continue;
if (j == 1) ans_[1][j] += ans_[0][j];
else if (j == i) ans_[1][j] += ans_[0][j - 1];
else ans_[1][j] += min(ans_[0][j], ans_[0][j - 1]);
}
swap(ans_[0], ans_[1]);
}
return *min_element(ans_[0].begin(), ans_[0].end());
}
private:
vector<vector<int>> ans_;
};