Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bb5c72f
0004_Solved
WAcry May 9, 2020
1d540ec
Rename 0004-median-of-two-sorted-arrays to 0004-median-of-two-sorted-…
WAcry May 9, 2020
0a528f2
0004_Solved
WAcry May 9, 2020
58d4e87
Merge pull request #85 from chilimyan/master
MisterBooo May 9, 2020
bcacf82
0004_Solved
WAcry May 9, 2020
74f1537
0004_Solved
WAcry May 9, 2020
76b7c5f
Merge pull request #86 from freetreer/master
MisterBooo May 9, 2020
938f18f
0025 Solved
anomot May 9, 2020
7ee0923
695
nettee May 9, 2020
1c55e0b
Solve 0137
peteryuhang May 9, 2020
5984175
Fix name typo
peteryuhang May 9, 2020
7163aaf
solved @xiaoshuai96
xiaoshuai96 May 10, 2020
1882475
Merge pull request #87 from anomot/master
MisterBooo May 11, 2020
c6ab9a2
Merge pull request #88 from nettee/695
MisterBooo May 11, 2020
cca9325
Merge pull request #89 from peteryuhang/master
MisterBooo May 11, 2020
9c0eb9d
Merge pull request #90 from xiaoshuai96/master
MisterBooo May 11, 2020
55ec12a
替换坏的gif
xiaoshuai96 May 11, 2020
b54bba9
0530 solved
zzilcc May 12, 2020
4f4ed06
add default return value to Two-Sum solution
underspirit May 13, 2020
0e9512c
Merge pull request #91 from xiaoshuai96/master
MisterBooo May 14, 2020
3302fb3
Merge pull request #92 from zzilcc/master
MisterBooo May 14, 2020
0a7cbf6
Solved 0260
peteryuhang May 17, 2020
1ce488f
solved @xiaoshuai96
xiaoshuai96 May 17, 2020
8989334
Merge pull request #93 from underspirit/bugfix-1
MisterBooo May 18, 2020
26d9265
Merge pull request #94 from peteryuhang/master
MisterBooo May 18, 2020
74af9ba
Merge pull request #95 from xiaoshuai96/master
MisterBooo May 18, 2020
566bcae
Solved 0120
peteryuhang May 23, 2020
62bcddc
Merge pull request #97 from peteryuhang/master
MisterBooo May 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Solved 0120
  • Loading branch information
peteryuhang committed May 23, 2020
commit 566bcae666fb7e41dadb251f649ebe7254a82993
Binary file added 0120-Triangle/Animation/120.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 0120-Triangle/Animation/120.m4v
Binary file not shown.
129 changes: 129 additions & 0 deletions 0120-Triangle/Article/0120-Triangle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# LeetCode 第 120 号问题:三角形最小路径和

> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步博客:https://www.algomooc.com

题目来源于 LeetCode 上第 120 号问题:三角形最小路径和。题目难度为 Medium,目前通过率为 64.7% 。


<br>


### 题目描述

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。



**示例 1:**

```
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
```
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

**说明:**

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

<br>

### 题目解析

给定一个三角形数组,需要求出从上到下的最小路径和,再确定这道题目可以用动态规划来解后,可以按照四个步骤来分析:

* 问题拆解:

这里的总问题是求出最小的路径和,路径是这里的分析重点,路径是由一个个元素组成的,`[i][j]` 位置的元素,经过这个元素的路径肯定也会经过 `[i - 1][j]` 或者 `[i - 1][j - 1]`,因此经过一个元素的路径和可以通过这个元素上面的一个或者两个元素的路径和得到

* 状态定义

状态的定义一般会和问题需要求解的答案联系在一起,这里其实有两种方式,一种是考虑路径从上到下,另外一种是考虑路径从下到上,因为元素的值是不变的,所以路径的方向不同也不会影响最后求得的路径和,如果是从上到下,你会发现,在考虑下面元素的时候,起始元素的路径只会从 [i - 1][j] 获得,每行当中的最后一个元素的路径只会从 [i - 1][j - 1] 获得,中间二者都可,这样不太好实现,因此这里考虑从下到上的方式,状态的定义就变成了 “**最后一行元素到当前元素的最小路径和**”,对于 [0][0] 这个元素来说,最后状态表示的就是我们的最终答案

* 递推方程

“状态定义” 中我们已经定义好了状态,递推方程就出来了
```
dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j]
```

* 实现

这里初始化时,我们需要将最后一行的元素填入状态数组中,然后就是按照前面分析的策略,从下到上计算即可

这里有一个小小的空间上面的优化,就是每次我们更新状态(dp)数组都是基于之前的结果,我们并不需要知道之前的之前的结果,平行的状态之间也没有相互影响,因此只用开一维数组即可

<br>

### 代码实现(空间优化前)

```java
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();

int[][] dp = new int[n][n];

List<Integer> lastRow = triangle.get(n - 1);

for (int i = 0; i < n; ++i) {
dp[n - 1][i] = lastRow.get(i);
}

for (int i = n - 2; i >= 0; --i) {
List<Integer> row = triangle.get(i);
for (int j = 0; j < i + 1; ++j) {
dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + row.get(j);
}
}

return dp[0][0];
}
```

<br>

### 代码实现(空间优化后)
```java
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();

int[] dp = new int[n];

List<Integer> lastRow = triangle.get(n - 1);

for (int i = 0; i < n; ++i) {
dp[i] = lastRow.get(i);
}

for (int i = n - 2; i >= 0; --i) {
List<Integer> row = triangle.get(i);
for (int j = 0; j < i + 1; ++j) { // i + 1 == row.size()
dp[j] = Math.min(dp[j], dp[j + 1]) + row.get(j);
}
}

return dp[0];
}
```

<br>

### 动画描述

![](../Animation/120.gif)

<br>

### 复杂度分析

时空复杂度从代码中都清晰可见,我们必须遍历三角形中的每个元素。时间复杂度就是 `O(1 + 2 + ... + n)`,也就是 `O(n^2)`。空间复杂度经过优化后是 `O(n)`。

![](../../Pictures/qrcode.jpg)