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.
这是一道典型的dp问题的题目,我的第一种解法很直接,思路也很简单就是自顶向下的遍历一整个三角数组,然后每一个节点都记录到这个节点的最短距离,这样时间复杂度和空间复杂度都是O(n * n)
以下是我的程序:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = 0;
int size = 0;
int pos = 0;
int sum = 0;
int small = 0;
std::vector<std::vector<int>> vec;
n = triangle.size();
if (n <= 0)
return sum;
std::vector<int> v;
v.push_back(triangle[0][0]);
vec.push_back(v);
for (int i = 1; i < n; i++) {
size = triangle[i].size();
std::vector<int> vec_small;
sum = vec[i - 1][0] + triangle[i][0];
vec_small.push_back(sum);
for (int j = 1; j < size - 1; j++) {
small = vec[i - 1][j - 1] <
vec[i - 1][j] ?
vec[i - 1][j - 1] : vec[i - 1][j];
sum = triangle[i][j] + small;
vec_small.push_back(sum);
}
sum = triangle[i][size - 1] +
vec[i - 1][size - 2];
vec_small.push_back(sum);
vec.push_back(vec_small);
}
n = vec.size();
size = vec[n - 1].size();
small = vec[n - 1][0];
for (int i = 1; i < size; i++)
if (small > vec[n - 1][i])
small = vec[n - 1][i];
return small;
}
};
但是我觉得这样的方式并不是很好,后来又改进了下,没有申请空间,而是直接在原来的三角数组上进行更改,虽然空间复杂度是O(1)但是这种方法的话不能保存数组的值,也不是很好,先看看程序:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
//这种方法直接利用的就是原来的数组,每一次记录的都是
//到当前节点的最小的步数之和。这样可以节省空间,但是不能保存下原来的数据
//我使用的是top-down的方法,但是在讨论里面别人使用的是bottom-up的方法;
//我觉得bottom-up的方法很好,节约空间,实现起来也不会很难
int n = 0;
int size = 0;
int pos = 0;
int sum = 0;
int small = 0;
n = triangle.size();
if (n <= 0)
return sum;
for (int i = 1; i < n; i++) {
size = triangle[i].size();
sum = triangle[i - 1][0] + triangle[i][0];
triangle[i][0] = sum;
for (int j = 1; j < size - 1; j++) {
small = triangle[i - 1][j - 1] <
triangle[i - 1][j] ?
triangle[i - 1][j - 1] :
triangle[i - 1][j];
sum = triangle[i][j] + small;
triangle[i][j] = sum;
}
sum = triangle[i][size - 1] +
triangle[i - 1][size - 2];
triangle[i][size - 1] = sum;
}
n = triangle.size();
size = triangle[n - 1].size();
small = triangle[n - 1][0];
for (int i = 1; i < size; i++)
if (small > triangle[n - 1][i])
small = triangle[n - 1][i];
return small;
}
};
最后看了讨论里面别人的算法,发现还可以从底部遍历回去,这样可以做到O(n * n)的时间复杂度和O(n)的空间复杂度,以下是程序:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
if (n == 0)
return 0;
int num = 0;
int size = triangle[n - 1].size();
int* arr = new int[size];
int small = 0;
for (int i = 0; i < size; i++)
arr[i] = triangle[n - 1][i];
for (int i = n - 2; i >= 0; i--) {
size = triangle[i].size();
for (int j = 0; j < size; j++) {
small = arr[j] < arr[j + 1] ?
arr[j] : arr[j + 1];
arr[j] = small + triangle[i][j];
}
}
num = arr[0];
delete []arr;
return num;
}
};
好啦,基本就是这样啦。
本文探讨了寻找三角形从顶到底的最小路径和的问题,提供了三种不同的算法实现方案,包括自顶向下的动态规划、就地修改输入数组以及自底向上的动态规划方法。

851

被折叠的 条评论
为什么被折叠?



