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.

这道题给了我们一个二维数组组成的三角形,让我们寻找一条自上而下的路径,使得路径和最短。那么那道题后还是先考虑下暴力破解,我们可以发现如果要遍历所有的路径的话,那可以是阶乘级的时间复杂度啊,OJ必灭之,趁早断了念想比较好。必须要优化时间复杂度啊,题目中给的例子很容易把人带偏,让人误以为贪婪算法可以解题,因为看题例子中的红色数组,在根数字2的下方选小的数字3,在3的下方选小的数字5,在5的下方选小的数字1,每次只要选下一层相邻的两个数字中较小的一个,似乎就能得到答案了。其实是不对的,贪婪算法可以带到了局部最小,但不能保证每次都带到全局最小,很有可能在其他的分支的底层的数字突然变的超级小,但是贪婪算法已经将其他所有分支剪掉了。所以为了保证我们能得到全局最小,动态规划Dynamic Programming还是不二之选啊。其实这道题和 Dungeon Game 非常的类似,都是用DP来求解的问题。那么其实我们可以不新建dp数组,而是直接复用triangle数组,我们希望一层一层的累加下来,从而使得 triangle[i][j] 是从最顶层到 (i, j) 位置的最小路径和,那么我们如何得到状态转移方程呢?其实也不难,因为每个结点能往下走的只有跟它相邻的两个数字,那么每个位置 (i, j) 也就只能从上层跟它相邻的两个位置过来,也就是 (i-1, j-1) 和 (i-1, j) 这两个位置,那么状态转移方程为:

triangle[i][j] = min(triangle[i - 1][j - 1], triangle[i - 1][j])

我们从第二行开始更新,注意两边的数字直接赋值上一行的边界值,那么最终我们只要在最底层找出值最小的数字,就是全局最小的路径和啦,代码如下:

解法一:

class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
for (int i = ; i < triangle.size(); ++i) {
for (int j = ; j < triangle[i].size(); ++j) {
if (j == ) {
triangle[i][j] += triangle[i - ][j];
} else if (j == triangle[i].size() - ) {
triangle[i][j] += triangle[i - ][j - ];
} else {
triangle[i][j] += min(triangle[i - ][j - ], triangle[i - ][j]);
}
}
}
return *min_element(triangle.back().begin(), triangle.back().end());
}
};

这种方法可以通过OJ,但是毕竟修改了原始数组triangle,并不是很理想的方法。在网上搜到一种更好的DP方法,这种方法复制了三角形最后一行,作为用来更新的一位数组。然后逐个遍历这个DP数组,对于每个数字,和它之后的元素比较选择较小的再加上面一行相邻位置的元素做为新的元素,然后一层一层的向上扫描,整个过程和冒泡排序的原理差不多,最后最小的元素都冒到前面,第一个元素即为所求。代码如下:

解法二:

class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> dp(triangle.back());
for (int i = (int)triangle.size() - ; i >= ; --i) {
for (int j = ; j <= i; ++j) {
dp[j] = min(dp[j], dp[j + ]) + triangle[i][j];
}
}
return dp[];
}
};

下面我们来看一个例子,对于输入数组:

-1

2   3

1  -1  -3

5   3   -1   2

下面我们来看DP数组的变换过程(红色数字为每次dp数组中值改变的位置):

DP:5  3  -1  2

DP:  3  -1  2

DP:4  -2  -1  2

DP:4  -2  -4  2

DP:  -2  -4  2

DP:0  -1  -4  2

DP:-2  -1  -4  2

参考资料:

https://leetcode.com/problems/triangle/

https://leetcode.com/problems/triangle/discuss/38730/DP-Solution-for-Triangle

https://leetcode.com/problems/triangle/discuss/38918/C%2B%2B-top-down-and-bottom-up-solutions.

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Triangle 三角形的更多相关文章

  1. LeetCode Triangle 三角形(最短路)

    题意:给一个用序列堆成的三角形,第n层的元素个数为n,从顶往下,每个元素可以选择与自己最近的两个下层元素往下走,类似一棵二叉树,求最短路. [], [,4], [6,,7], [4,,8,3] 注意: ...

  2. [LeetCode 120] - 三角形(Triangle)

    问题 给出一个三角形,找出从顶部至底部的最小路径和.每一步你只能移动到下一行的邻接数字. 例如,给出如下三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 从顶部至底部的最 ...

  3. LeetCode 976. Largest Perimeter Triangle (三角形的最大周长)

    题目标签:Array 题目给了我们一个 边长的 array, 让我们找出 最大边长和的三角形,当然前提得是这三条边能组成三角形.如果array 里得边长组成不了三角形,返回0. 最直接的理解就是,找到 ...

  4. LeetCode 976. 三角形的最大周长(Largest Perimeter Triangle) 33

    976. 三角形的最大周长 976. Largest Perimeter Triangle 题目描述 给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的.面积不为零的三角形的最大周长. ...

  5. LeetCode 120. Triangle三角形最小路径和 (C++)

    题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...

  6. LeetCode 120. 三角形最小路径和(Triangle)

    题目描述 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 自顶向下的最小路径 ...

  7. LeetCode 120. Triangle (三角形最小路径和)详解

    题目详情 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 自顶向下的最小路径 ...

  8. leetcode — triangle

    /** * Source : https://oj.leetcode.com/problems/triangle/ * * * Given a triangle, find the minimum p ...

  9. 120 Triangle 三角形最小路径和

    给出一个三角形(数据数组),找出从上往下的最小路径和.每一步只能移动到下一行中的相邻结点上.比如,给你如下三角形:[     [2],    [3,4],   [6,5,7],  [4,1,8,3]] ...

随机推荐

  1. 模仿东京首页banner轮播,京东新闻上下滚动动画实现(动画实现)

    接着上篇 微信小程序-阅读小程序demo写:http://www.cnblogs.com/muyixiaoguang/p/5917986.html 首页banner动画实现 京东新闻上下动画实现 想着 ...

  2. 利用Python进行数据分析(8) pandas基础: Series和DataFrame的基本操作

    一.reindex() 方法:重新索引 针对 Series   重新索引指的是根据index参数重新进行排序. 如果传入的索引值在数据里不存在,则不会报错,而是添加缺失值的新行. 不想用缺失值,可以用 ...

  3. Basic Tutorials of Redis(3) -Hash

    When you first saw the name of Hash,what do you think?HashSet,HashTable or other data structs of C#? ...

  4. IL实现简单的IOC容器

    既然了解了IL的接口和动态类之间的知识,何不使用进来项目实验一下呢?而第一反应就是想到了平时经常说的IOC容器,在园子里搜索了一下也有这类型的文章http://www.cnblogs.com/kkll ...

  5. [Winform] DataGridView 总结(FAQ)

    Q1.  如何使单元格不可编辑? A:设置 ReadOnly 属性,可以设置的对象包括 DataGridViewRow(行).DataGridViewColumn(列).DataGridViewCel ...

  6. .NET正则表达式基础入门

    这是我第一次写的博客,个人觉得十分不容易.以前看别人写的博客文字十分流畅,到自己来写却发现十分困难,还是感谢那些为技术而奉献自己力量的人吧. 本教程编写之前,博主阅读了<正则指引>这本入门 ...

  7. Yii2.X 多语言-类图

  8. flask+sqlite3+echarts2+ajax数据可视化报错:UnicodeDecodeError: 'utf8' codec can't decode byte解决方法

    flask+sqlite3+echarts2+ajax数据可视化报错: UnicodeDecodeError: 'utf8' codec can't decode byte 解决方法: 将 py文件和 ...

  9. Android Studio使用时源码到处报红色警告,运行时又没错

    转载地址:http://www.07net01.com/program/2016/04/1452749.html [摘要:正在AS上开辟时,碰到那个题目,翻开全部的Java源文件,右边一起标赤色,找没 ...

  10. java保留两位小数4种方法

    import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public c ...