题目描述
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
解题思路
考虑用动态规划解题。用一个数组dp[n]记录每层各个节点为路径终点的最小路径和,这样每遍历到新的一层,就根据上一层记录的dp来更新本层的dp.由于以某节点为终点的路径的上一个节点可以是两个不同的节点,而更新dp会覆盖路径中的节点,所以用f来记录对应本节点在上一层靠左的最小路径,并且用l记录上一层最右端的最小路径。具体而言分为三种情况:
- 若n=0,即遍历到本层的第一个节点,那么以此节点为终点的路径只有一条,直接更新dp[n]=dp[n]+triangle[i][j]
- 若n=i,即遍历到本层的最后一个节点,那么以此节点为终点的路径只有一条,直接更新dp[n]=l+triangle[i][j]
- 若0<n<i,即遍历到中间节点,首先记录最小路径和path=min(f+triangle[i][j],dp[j]+triangle[i][j]),然后更新f=dp[j],dp[j]=path
如果遍历到最后一层,那么用minSum记录该层的最小路径和,没计算出一个节点的最小路径和,就更新minSum
代码
1 class Solution { 2 public: 3 int minimumTotal(vector<vector<int>>& triangle) { 4 int n=triangle.size(); 5 if(n==1) 6 return triangle[0][0]; 7 vector<int> dp(n,triangle[0][0]); 8 int minSum=INT_MAX; 9 int f,l; 10 for(int i=1;i<n;i++){ 11 f=dp[0]; 12 l=dp[i-1]; 13 for(int j=0;j<=i;j++){ 14 if(j==0) 15 dp[j]+=triangle[i][j]; 16 else if(j==i) 17 dp[j]=l+triangle[i][j]; 18 else{ 19 int path=min(f+triangle[i][j],dp[j]+triangle[i][j]); 20 f=dp[j]; 21 dp[j]=path; 22 } 23 if(i==n-1) 24 if(dp[j]<minSum) 25 minSum=dp[j]; 26 } 27 } 28 return minSum; 29 } 30 };