问题描述
笔记
代码1
设置buff[i][j]为:以元素(i,j)结尾的最小路径和。
buff[i][j]
应该是buff[i-1][j-1]
和buff[i-1][j]
中的较小值再加上当前的triangle[i][j]
。
则状态转移方程为:
buff[i][j] = min(buff[i-1][j-1], buff[i-1][j] + triangle[i][j]
初始条件为:
buff[0][0] = triangle[0][0]
注意
判断越界问题也用到了一个小技巧,忘了从哪学来的了。
//要取buff[i-1][j-1],和buff[i-1][j],但是要保证不越界。
//第i-1行的j的取值范围为[0, i-1]
int lo = max(0, j-1);//当j-1小于0的时候只取0,大于等于0的时候取自身。
int hi = min(j, i-1);//当j大于i-1的时候只取i-1,小于等于i-1的时候取自身。
代码2
题目要求优化空间复杂度。其实不需要用二维数组,因为每一行的值只与上一行的值相关,因此可以只用一行做缓存即可。(代码2)
在这里用到了背包问题中的小技巧,每一行从后往前更新,以防覆盖前面要使用的值。
注意
看来,要将二维空间节省成一维空间的时候,都要考虑一下从后往前向前更新这一小技巧。
代码1
class Solution {
public:
/**
* @param triangle: a list of lists of integers.
* @return: An integer, minimum path sum.
*/
int minimumTotal(vector<vector<int> > &triangle) {
// write your code here
const int len = triangle.size();
vector<vector<int>> buff(len, vector<int>(len));
buff[0][0] = triangle[0][0];
for (int i = 1; i < len; i++)
{
for (int j = 0; j <= i; j++)
{
// 要取buff[i-1][j-1],和buff[i-1][j],但是要保证不越界。
// 第i-1行的j的取值范围为[0, i-1]
int lo = max(0, j-1);
int hi = min(j, i-1);
buff[i][j] = min(buff[i-1][lo], buff[i-1][hi]) + triangle[i][j];
}
}
int res = buff[len-1][0];
for (int i = 1; i < len; i++)
res = min(res, buff[len-1][i]);
return res;
}
};
代码2
class Solution {
public:
/**
* @param triangle: a list of lists of integers.
* @return: An integer, minimum path sum.
*/
int minimumTotal(vector<vector<int> > &triangle) {
// write your code here
const int len = triangle.size();
vector<int> buff(len);
buff[0] = triangle[0][0];
for (int i = 1; i < len; i++)
{
for (int j = i; j >= 0; j--)
{
int lo = max(0, j-1);
int hi = min(j, i-1);
buff[j] = min(buff[lo], buff[hi]) + triangle[i][j];
}
}
int res = buff[0];
for (int i = 1; i < len; i++)
res = min(res, buff[i]);
return res;
}
};