给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
1.自顶向下+备忘录法
对于每一个节点,递归地求出他(左右两个孩子的值+自身节点值)最小的那一个记为tmp,并保存在辅助数组res中,以供下一次计算同一节点值时使用,这样做可以避免大量的重复计算,但是需要O(m*n)的额外空间。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int m=triangle.size();
int n=triangle[m-1].size();
vector<vector<int> >res(m,vector<int>(n));
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
res[i][j]=INT_MAX;
return minimumTotal(triangle,res,0,0);
}
int minimumTotal(vector<vector<int>>& triangle,vector<vector<int>>& res,int i,int j){
if(res[i][j] != INT_MAX)
return res[i][j];
if(i==triangle.size()-1)
return triangle[i][j];
int tmp = INT_MAX;
if(i<triangle.size()-1){
tmp=min(minimumTotal(triangle,res,i+1,j)+triangle[i][j],minimumTotal(triangle,res,i+1,j+1)+triangle[i][j]);
}
res[i][j] = min(tmp,res[i][j]);
return res[i][j];
}
};
2.自底向上法
“自底向上”的DP非常简单:我们从最下面一行的节点开始;这些节点的最小路径和是节点本身的值。从这里,第layer行第j个节点的最小路径和将是它的两个子节点的路径和中较小的一个加上它自身的值,即
minpath[layer][j] = min( minpath[layer+1][j], minpath[layer+1][j+1]) + triangle[layer][j];
由于行minpath[layer+1]在计算完minpath[layer]之后就没用了,所以我们可以简单地将minpath设置为一个一维数组,每次计算都迭代更新它自己
minpath[j] = min( minpath[j], minpath[j+1]) + triangle[layer][j];
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int m=triangle.size();
vector<int> ans(triangle.back()); //将三角形最后一行复制给辅助数组
for(int layer= m-2; layer >= 0;layer--) //从倒数第二行开始迭代
for(int j=0; j<triangle[layer].size();j++)
ans[j]=min(ans[j],ans[j+1])+triangle[layer][j];
return ans[0];
}
};