给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
dp1[i] 表示到达上一行第i个位置需要的最少路径和, dp[i]表示到达当前行第i个位置需要走的最小路径和; 到达第 i 行第 j 列只能通过第 i-1 行的 j-1 列或者 j 列到达,
所以可以得到关系式dp[j] = min(dp[j-1], dp[j]) + triangle[i][j]; 边界条件是每一行的最左边和最右边; 该方法的额外空间是O(n)
1 #include<algorithm> 2 class Solution { 3 public: 4 int minimumTotal(vector<vector<int>>& triangle) { 5 int n=triangle.size(), i, j; 6 vector<int> dp(n, 0), dp1(n, 0); 7 dp1[0]=dp[0]=triangle[0][0]; 8 for(i=1; i<n; i++){ 9 for(j=0; j<triangle[i].size(); j++){ 10 if(j==0) dp[j] = dp1[j] + triangle[i][j]; 11 else if(j==triangle[i].size()-1) dp[j] = dp1[j-1] + triangle[i][j]; 12 else dp[j] = min(dp1[j-1], dp1[j]) + triangle[i][j]; 13 } 14 swap(dp1, dp); 15 } 16 sort(dp1.begin(), dp1.end()); 17 return dp1[0]; 18 } 19 };
每一行从右到左遍历,可以减少数组复制的过程;
#include<algorithm> class Solution { public: int minimumTotal(vector<vector<int>>& triangle) { int n = triangle.size(), i, j; vector<int>dp(n); dp[0] = triangle[0][0]; for(int i = 1; i < n; i++){ dp[i] = dp[i - 1] + triangle[i][i]; for(int j = i - 1; j > 0; j--) dp[j] = triangle[i][j] + min(dp[j], dp[j - 1]); dp[0] = dp[0] + triangle[i][0]; } sort(dp.begin(), dp.end()); return dp[0]; } };