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. 【分布式】Zookeeper的Leader选举

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  2. php内核分析(一)-sapi_module_struct

    这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux 首先是寻找php的入口,php有很多种模式,apache,php-fpm, cli模式,我要入手的话,只能先从最简单的cl ...

  3. 一位同事对 Rafy 框架的一些建议及我的回复

    下面是一位同事对当前的产品开发框架提出的一些建议,以及我的回复.我觉得一些问题提得有一定的代表性,在征得本人同意后,将本邮件发布在博客中. 同时,也非常希望对框架.产品有好的建议的小伙伴,都可以给我发 ...

  4. QT 删除文件指定目录

    bool deleteDir(const QString &dirName) { QDir directory(dirName); if (!directory.exists()) { ret ...

  5. 【译】Asp.net mvc 使用ITextSharp PDF to HTML (解决img标签问题)

    前言:因项目需求,需要将HTML代码转成PDF.大致上已经实现了,可以是发现使用ITextSharp(我现在的版本是5.5.9)的时候,img标签中的src只能跟绝对路径. 在百度上找了一个上午,有一 ...

  6. 1、Python基本概念

    1.数 python中有4种类型的数--整数.长整数.浮点数和复数 2.字符串 单引号.双引号或者三引号包含的字符序列,如: 'char' #单引号 "char" #双引号 ''' ...

  7. 来玩Play框架07 静态文件

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Play框架的主要功能是提供动态响应的内容.但一个网络项目中必然有大量的静态内容, ...

  8. datatables中的Options总结(1)

    datatables中的Options总结(1) 最近一直研究dataTables插件,下面是总结的所有的选项内容,用了帮助学习datatables插件. 这些选项的配置在$().Datatable( ...

  9. Position属性四个值:static、fixed、relative、absolute的区别和用法

    1.static(静态定位):默认值.没有定位,元素出现在正常的文档流中(如果设置 top, bottom, left, right, z-index这些属性就不起做作了). 2.relative(相 ...

  10. CSS3和javascript中的transform

    在javascript中,WebkitTransform 大概相当于 transform .transform 为标准,WebkitTransform 适用于Webkit浏览器.js中的WebkitT ...