题目
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.
递归方法
这道题的数据结构很像二叉树的结构,我们可以用递归遍历二叉树的思想来遍历所有的可能的路径,以求出最小的路径权重和。
定义一个辅助的递归函数 int myRecursion(vector<vector<int>>& triangle, int i, int j),这个第一个参数为原三角形,第二和第三个参数(i,j)代表当前遍历到的三角形的节点位置,返回值为以当前节点(i,j)出发到底层的最小路径权重和。
所以我们从(0,0)节点处开始调用myRecursion,在myRecursion函数内部,分别计算(i,j)节点相邻两条路径的最小路径权重和,然后取两者的最小值加上本节点(i,j)的权重,作为以当前节点(i,j)出发到底层的最小路径权重和。
代码如下:
class Solution {
public:
int myRecursion(vector<vector<int>>& triangle, int i, int j) {
int row = triangle.size();
int col = triangle[i].size();
int result1;
int result2;
if (i == row - 1) {
return triangle[i][j];
}
else if (i < row - 1) {
result1 = myRecursion(triangle, i + 1, j) + triangle[i][j];
result2 = myRecursion(triangle, i + 1, j + 1) + triangle[i][j];
return result1 < result2 ? result1 : result2;
}
}
int minimumTotal(vector<vector<int>>& triangle) {
return myRecursion(triangle, 0, 0);
}
};
递归的方法从正确性来看是正确的,但在LeetCode中测试时只能通过45/46个测例,最后一个测例不通过。原因是最后一个测例三角形的元素太多,而递归方法的开销较大,出现了Time Limit Exceeded错误。所以在这道题里面,递归方法不一定适用。
动态规划方法
动态规划方法是正确的解决办法。
利用动态规划的方法计算,按照题目的三角形数据,计算过程如下:
生命一个int类型数组all_dist,对于原来的三角形,遍历到第二层时,有 2+3=5和2+4=6,我们要把遍历到当前层各节点所经历的最小权重和保存到all_dist中,所以all_dist保存当前层的计算结果[5,6]。
接下来,当前层为[6,5,7]。对于当前行中的每一个元素,计算当前元素权重与上一行中相邻的2个元素权重和的最小值,然后把这个最小值更新到当前元素对应all_dist数组的位置。不断进行下去,直到最后一行为止。
代码如下:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int row = triangle.size();
vector<int> all_dist(1000, 0);
int result = 0;
all_dist[0] = triangle[0][0];
for (int i = 1; i < row; i++) {
vector<int> temp_all_dist(all_dist);
for (int j = 1; j < i; j++) {
all_dist[j] = temp_all_dist[j] + triangle[i][j] < temp_all_dist[j - 1] + triangle[i][j] ?
temp_all_dist[j] + triangle[i][j] : temp_all_dist[j - 1] + triangle[i][j];
}
all_dist[0] = temp_all_dist[0] + triangle[i][0];
all_dist[i] = temp_all_dist[i - 1] + triangle[i][i];
}
result = all_dist[0];
for (int i = 1; i < row; i++) {
result = result < all_dist[i] ? result : all_dist[i];
}
return result;
}
};