剑指 Offer II 100. 三角形中最小路径之和
一、题目
原题链接:剑指 Offer II 100. 三角形中最小路径之和
这道题和leetcode上的 120. 三角形最小路径和 题相同。
1.题目描述
给定一个三角形 triangle ,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。
示例 1:
输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出:11
解释:如下面简图所示:
2
3 4
6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
示例 2:
输入:triangle = [[-10]]
输出:-10
提示:
- 1 <= triangle.length <= 200
- triangle[0].length == 1
- triangle[i].length == triangle[i - 1].length + 1
- -104 <= triangle[i][j] <= 104
2.基础框架
C++基础框架代码如下:
int mininumTotal(vector<vector<int> >& triangle){
}
3.解题思路
- 题目分析
-
题目目标求自顶向下的最小路径和,属于最小值问题。
-
第
i
层的路径结点j可以走到第下一层即i + 1
层的路径结点j
或j + 1
,可以转换成如下:第
i
层的路径结点j
可以通过上一层即i-1
层的路径节点j - 1
和j
转移过来。 -
但仔细留意发现:
- 当
j == 0
,不能从上一层的第j - 1
的路径结点转移过来, - 当
j == triangle.size() - 1
,不能从上一层的第j
路径结点转移过来
所以需要对上面的情况,分别进行赋值。
- 当
-
当访问到最后一层,可以通过sort来对最后一行进行排序,将最后一行的数组排序后的第一个元素返回即为最小路径和。
-
实现代码:
int minimumTotal(vector<vector<int>>& triangle) { vector<vector<int> > dp(triangle.size(), vector<int>(triangle[0].size())); for (int i = 0; i < triangle.size(); i++) dp[i].resize(triangle[i].size()); dp[0][0] = triangle[0][0]; int i; for (i = 1; i < triangle.size(); i++) { for (int j = 0; j < triangle[i].size(); j++) { if (j == 0) dp[i][j] = triangle[i][j] + dp[i - 1][j]; else if (j == triangle[i].size() - 1) dp[i][j] = triangle[i][j] + dp[i - 1][j - 1]; else dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j]; } } sort(dp[i - 1].begin(), dp[i - 1].end()); return dp[i - 1][0]; }
-
优化的思路:
自底向上进行遍历,这样的好处是减少没有了之前逻辑中的分情况赋值的情况,而且到顶部的时候一定是得到最小路径和,相比于上面的代码最后还要进行排序筛选最小路径和的方式,自底向上的逻辑实在是巴适得不要不要。
-
优化思路后的代码:
int minimumTotal(vector<vector<int>>& triangle) { for (int i = triangle.size() - 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]; }