一、 题目
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
如图,在一个三角形二维数组中有一系列数,求出从顶层到底层最小和的路径。
二、 分析
思路1递归解决,求以某个数为起点的最小和,可以先求出以跟它相邻的下一层的两个数为起点的最小和,然后取两者的更小者,最后与该数相加即可。不过此方法超时
//递归,超时 class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { return minimumTotal(triangle,0,0); } int minimumTotal(vector<vector<int> > &triangle,int row,int col) { if(row == triangle.size()-1) return triangle[row][col]; return min(minimumTotal(triangle,row+1,col),minimumTotal(triangle,row+1,col+1))+ triangle[row][col]; } };
思路2 很明显是动态规划的题目,求一个三角形二维数组从顶到低端的最小路径和。维护到某一个元素的最小路径和,那么在某一个元素i,j的最小路径和就是它上层对应的相邻两个元素的最小路径和加上自己的值,递推式是ans[i][j]=min(ans[i-1][j-1],ans[i-1][j])+triangle[i][j]。最后扫描一遍最后一层的路径和,取出最小的即可。每个元素需要维护一次,总共有1+2+...+n=n*(n+1)/2个元素,时间复杂度是O(n^2)。而空间上每次只需维护一层即可(因为当前层只用到上一层的元素),所以空间复杂度是O(n)。
class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int len = triangle.size(); if(len == 0) return 0; if(len == 1) return triangle[0][0]; int ans[len]; ans[0] = triangle[0][0]; for(int i=1;i<len;i++){ ans[i] = ans[i-1] + triangle[i][i]; for(int j=i-1;j>=1;j--) ans[j] = min(ans[j],ans[j-1]) + triangle[i][j]; ans[0] = ans[0] + triangle[i][0]; } int minLen = ans[0]; for(int i=1;i<len;i++) if(ans[i]<minLen) minLen = ans[i]; return minLen; } };
思路3换个角度考虑,如果这道题不自顶向下进行动态规划,而是放过来自底向上来规划,递归式只是变成下一层对应的相邻两个元素的最小路径和加上自己的值,原理和上面的方法是相同的,这样考虑到优势在于不需要最后对于所有路径找最小的,而且第一个元素和最后元素也不需要单独处理。
class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int len = triangle.size(); if(len == 0) return 0; //vector<int> ans(len);//效果一样 int ans[len]; //把最底层初始 for(int i=0;i<len;i++){ ans[i] = triangle[len-1][i]; } //从倒数第二层向上DP直到最后只剩下一个数,即为所求 for(int i=len-2;i>=0;i--){ for(int j=0;j<=i;j++){ ans[j] = min(ans[j],ans[j+1])+triangle[i][j]; } } return ans[0]; } };
原文地址:http://blog.csdn.net/zzucsliang/article/details/41854383