给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/triangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:首先利用直接递归的方法。(超时,有重复计算)
定义状态:f[i][j]
为(i,j)
点到底边的最小路径和。则递归方程为:
f(i,j) = min(f(i+1,j),f(i+1,j+1)) + triangle[i][j]
代码实现:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
return dfs(triangle,0,0);
}
int dfs(vector<vector<int>>&triangle,int i,int j)
{
if(i == triangle.size())
return 0;
return min(dfs(triangle,i+1,j),dfs(triangle,i+1,j+1)) + triangle[i][j];
}
};
思路二:动态规划。状态仍然是思路一定义的一样。但是我们要从底往上进行递推。
代码实现:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
if(n == 0)
return 0;
vector<vector<int>>f(n+1,vector<int>(n+1,0));
//从三角形的最后一行开始递推
for(int i = n-1;i >= 0;--i)
{
for(int j = 0;j <=i;++j)
{
f[i][j] = min(f[i+1][j],f[i+1][j+1]) + triangle[i][j];
}
}
return f[0][0];
}
};
思路三:优化空间,实际上我们再用数组的时候只用到了下一层的数据,而这是刚刚计算过的,所以可以优化空间。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
if(n == 0)
return 0;
vector<int>f(n+1,0);
//从三角形的最后一行开始递推
for(int i = n-1;i >= 0;--i)
{
for(int j = 0;j <=i;++j)
{
f[j] = min(f[j],f[j+1]) + triangle[i][j];
}
}
return f[0];
}
};