120. Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
思路
矩阵型动态规划问题
有两种方法:自上而下和自下而上
方法一:自下而上
从最底层到(i, j)所用的最短距离等于该点左下角(i+1, j)和右下角(i+1, j+1)之间的最小值加上当前点的值
triangle[i][j] += min(triangle[i+1][j] + triangle[i+1][j+1])
最终的值是: triangle[0][0]
方法二:自上而下
从顶层到(i, j)所用的最短距离等于该点左下角(i+1, j)和右下角(i+1, j+1)之间的最小值加上当前点的值
triangle[i][j] += min(triangle[i-1][j-1] + triangle[i-1][j])
注意:下一行的首尾分别只能和上一行的首尾相邻,其他元素可以和上一行的两个元素相邻
最终的值是:最后一行的最小值
C++11
方法一:自下而上
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
// 从倒数第二行开始计算
for (int i = triangle.size() - 2; i >= 0; --i)
// 当前行元素的个数等于i+1
for (int j = 0; j <= i; ++j)
triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1]);
return triangle[0][0];
}
};
方法二:自上而下
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> cache; // 存储前一行计算后的值
for (auto &cur_v : triangle) {
// 当前行首尾直接加上上一行的首尾
if (!cache.empty()) {
cur_v.front() += cache.front();
cur_v.back() += cache.back();
}
for (size_t i = 1; i < cache.size(); ++i)
cur_v[i] += min(cache.at(i-1), cache.at(i));
// 当前行计算完后赋值给cache,便于下一次迭代计算
cache = cur_v;
}
// 返回最后一行计算后的最小值
return *min_element(cache.cbegin(), cache.cend());
}
};