题目
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
空间复杂度限制为:O(n) n 为三角形的层数
思路
根据题意,可以使用一个大小为 n 的数组存储每一层的累加和,即每到新的一层,计算当前点与上一层累加和中可以取的最小值相加,(因为是相邻节点,每个点所以可取的值最多两个)。
使用大小为 n 的数组存储此值,从第一层往下依次计算,比如 第二层节点 j , 使用 arr 存储每个累加和的话,arr[ j ] = min(arr[ j ],arr[ j - 1]) + val[1][ j ], 但是由于 arr[j - 1]刚计算结束,所以已经被覆盖为新的值,所以结果不正确。
技巧点:从下往上计算每一层的累加和,一方面可以避免覆盖值的问题,另一方面最后arr【0】就是结果的最小值,而不用再去遍历 arr 也就是说,arr【j】 = min(arr【j】,arr【j+1】) + val【j】
代码
#include<iostream>
#include<vector>
using namespace std;
// 三角形最小路径和
// 要求空间复杂度是O(n) n 为 三角形层数
// 思路: 采用一个数组,存储已经计算好的和,到新的一层后,每个元素与其可以相加的已经计算好的元素的最小值相加
// 由于空间的限制,使用一个 n 大小的数组存储的时候,会使用被覆盖后的值,所以,从底层往上计算
class Solution {
public:
inline int min(int a, int b)
{
return a < b ? a : b;
}
int minimumTotal(vector<vector<int>>& triangle)
{
// 判断
if (triangle.size() == 0)
{
return 0;
}
// 初始化为最后一层
vector<int> arr = triangle[triangle.size() - 1];
// 从倒数第二层计算
for (int i = triangle.size() - 2; i >= 0; i--)
{
for (int j = 0; j < triangle[i].size(); j++)
{
arr[j] = triangle[i][j] + min(arr[j], arr[j + 1]); // 刚好不会覆盖
}
}
return arr[0];
}
};
有问题还望指出。