题目
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.
Solution (O(n) + O(n))
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> extra(triangle[triangle.size()-1]);
for (int i = triangle.size() - 2; i >= 0; i--) {
for (int j = 0; j < i + 1; j++) {
extra[j] = (triangle[i][j] + min (extra[j], extra[j+1]));
}
}
return extra[0];
}
};
题解
这道题写的还挺顺的,代码量也很少,为了便于理解,可以先看看我之前写的一个版本的代码(这个版的空间复杂度严格来说是 O(sizeof the triangle
) 的。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int height = triangle.size();
for (int i = height - 2; i >= 0; i--) {
for (int j = 0; j < triangle[i].size(); j++) {
triangle[i][j] += min (triangle[i+1][j] , triangle[i+1][j+1]);
}
}
return triangle[0][0];
}
};
思路是这样的,每个子三角形的最小花费就是它的最上端的顶点加上它下边的三角形的最小花费,也就是说,它的花费就是他的费用,加上以他左边子节点为顶点的子三角形的最小花费,或者加上他右边子节点为顶点的子三角形的最小花费(选择其中少的那个)。这明显是个递归的问题,我们可以用动态规划来求解。
m i n C o s t i j = m i n C o s t i j + m i n { m i n C o s t i + 1 , j , m i n C o s t i + 1 , j + 1 } minCost_{ij} = minCost_{ij} + min \{ minCost_{i+1,j}, minCost_{i+1,j+1} \} minCostij=minCostij+min{minCosti+1,j,minCosti+1,j+1}
所以可以建立一个二维数组,存储minCost
信息,从下往上数,先求下层的,再求上层的,就可以很自然的求解了。
我们要做到 O(n) 的空间复杂度的话,就要把这个状态压缩一下,可以发现,每个minCost[i][j]
需要用到的就只有下一层(i+1
层)的j
和j+1
,而不需要用到j-1
之类的信息,所以我们只要保证每次从前往后进行第二次遍历,就只需要保存一层的minCost
即可了,就做到了 O(n) 的额外空间。
分析
- 时间复杂度是进行 n 2 / 2 n^2/2 n2/2 次的循环,因此为O(n^2)
- 空间复杂度做到了 O(n)。