LeetCode 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.
分析
这道题采用动态规划,dp[i][j]表示从第0行到第i行以triangle[i][j]元素结尾的最小sum和,而到达第i行的最小sum和是min{dp[i][j]|0<=j<triangle.size()-1}.
状态转移方程,如果triangle[i][j]是该行的第一个,即j=0,则dp[i][j]=dp[i-1][j]+triangle[i][j];
如果triangle[i][j]是该行的最后一个数,即j=triangle[i].size()-1,则dp[i][j]=dp[i-1][j-1]+triangle[i][j];
否则,dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j];
const int inf=999999;
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<vector<int>> dp;
for(int i=1;i<=triangle.size();i++){
vector<int> vi(i,inf);
dp.push_back(vi);
}
dp[0][0]=triangle[0][0];
int minvalue=dp[0][0];
for(int i=1;i<triangle.size();i++){
minvalue=inf;
for(int j=0;j<triangle[i].size();j++){
if(j==0)
dp[i][j]=dp[i-1][j]+triangle[i][j];
else if(j==triangle[i].size()-1)
dp[i][j]=dp[i-1][j-1]+triangle[i][j];
else
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j];
minvalue=min(minvalue,dp[i][j]);
}
}
return minvalue;
}
};
空间复杂度为O(n)的,n是行数的解法如下
const int inf=999999;
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> dp(triangle.size(),inf);
dp[0]=triangle[0][0];
int minvalue=dp[0];
for(int i=1;i<triangle.size();i++){
minvalue=inf;
for(int j=0;j<triangle[i].size();j++){
if(j==0)
dp[j]=triangle[i-1][j]+triangle[i][j];
else if(j==triangle[i].size()-1)
dp[j]=triangle[i-1][j-1]+triangle[i][j];
else
dp[j]=min(triangle[i-1][j-1],triangle[i-1][j])+triangle[i][j];
minvalue=min(minvalue,dp[j]);
}
triangle[i]=dp;
}
return minvalue;
}
};
写法更简洁,是从底部向上更新dp的写法。
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle)
{
vector<int> mini = triangle[triangle.size()-1];
for ( int i = triangle.size() - 2; i>= 0 ; --i )
for ( int j = 0; j < triangle[i].size() ; ++ j )
mini[j] = triangle[i][j] + min(mini[j],mini[j+1]);
return mini[0];
}
};