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. .NET 开源SqlServer ORM框架 SqlSugar 3.0 API

    3.1.x ,将作为3.X系统的最后一个版本,下面将会开发 全新的功能 更新列表:https://github.com/sunkaixuan/SqlSugar/releases 优点: SqlSuga ...

  2. php内核分析(七)-扩展

    这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux. 我们研究下反射这个扩展. 反射这个扩展目录是存在在:ext/reflection.其实里面的代码很简单.一个.h文件,一 ...

  3. 如果你也会C#,那不妨了解下F#(2):数值运算和流程控制语法

    本文链接:http://www.cnblogs.com/hjklin/p/fs-for-cs-dev-2.html 一些废话 一门语言火不火,与语言本身并没太大关系,主要看语言的推广. 推广得好,用的 ...

  4. Delphi_05_Delphi_Object_Pascal_基本语法_03

    继续Delphi的学习之旅, 废话不多说,直接贴代码. { Delphi基本语法 1.对象 2.指针 3.类型别名 和 类型转换 } program DelphiObject; {$APPTYPE C ...

  5. [连载]《C#通讯(串口和网络)框架的设计与实现》- 9.插件引擎设计

    目       录 第九章           插件引擎设计... 2 9.1           框架的契约-接口... 2 9.2           插件的雏形-抽象类... 3 9.3     ...

  6. 使用 jQuery Ajax 在页面滚动时从服务器加载数据

    简介 文本将演示怎么在滚动滚动条时从服务器端下载数据.用AJAX技术从服务器端加载数据有助于改善任何web应用的性能表现,因为在打开页面时,只有一屏的数据从服务器端加载了,需要更多的数据时,可以随着用 ...

  7. sql case when...then...else...end 选择判断

    达到的需求为: 吓数收回日期为空:当接单日期不等于空和当天减接单日期大于3天时,为1,否则为0:当接单日期为空.最大发织交期不等于空和当天减去最大发织交期大于3天时,为1,否则为0:当接单日期和发织交 ...

  8. 初探React,将我们的View标签化

    前言 我之前喜欢玩一款游戏:全民飞机大战,而且有点痴迷其中,如果你想站在游戏的第一阶梯,便需要不断的练技术练装备,但是腾讯的游戏一般而言是有点恶心的,他会不断的出新飞机.新装备.新宠物,所以,很多时候 ...

  9. HTML5应用程序缓存Application Cache

    什么是Application Cache HTML5引入了应用程序缓存技术,意味着web应用可进行缓存,并在没有网络的情况下使用,通过创建cache manifest文件,可以轻松的创建离线应用. A ...

  10. 3.2 js六大数据类型

    js中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Null,Undefined),和一种混合数据类型(Object). 前面说到js中变量是松散类型的,因此有时候 ...