Skip to content

Commit 82f8c87

Browse files
author
lucifer
committed
2 parents 8cdd655 + 3cc9454 commit 82f8c87

File tree

5 files changed

+33
-49
lines changed

5 files changed

+33
-49
lines changed

problems/124.binary-tree-maximum-path-sum.md

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,27 +56,23 @@ Output: 42
5656

5757
![124.binary-tree-maximum-path-sum](https://tva1.sinaimg.cn/large/007S8ZIlly1ghluai4m6dj30hu0cdq46.jpg)
5858

59-
大家可以结合上面的demo来继续理解一下path, 除非你理解了path,否则不要往下看。
59+
如图红色的部分是最大路径上的节点。大家可以结合上面的demo来继续理解一下path, 除非你理解了path,否则不要往下看。
6060

6161

62-
树的题目,基本都是考察递归思想的。因此我们需要思考如何去定义我们的递归函数,
63-
在这里我定义了一个递归函数,它的功能是,`返回以当前节点为根节点的MathPath`
64-
但是有两个条件:
62+
树的题目,基本都是考察递归思想的。因此我们需要思考如何去定义我们的递归函数,在这里我定义了一个递归函数,它的功能是,`返回以当前节点为根节点的MaxPath`
6563

66-
1. 第一是跟节点必须选择
67-
2. 第二是左右子树只能选择一个
64+
但是有两个条件:
6865

69-
为什么要有这两个条件?
66+
1. 根节点必须选择
67+
2. 左右子树只能选择一个
7068

71-
我的想法是原问题可以转化为:
69+
为什么要有这两个条件?
7270

73-
以每一个节点为根节点,我们分别求出max path,最后计算最大值,因此第一个条件需要满足.
71+
我的想法是原问题可以转化为:以每一个节点为根节点,分别求出 MaxPath,最后计算最大值因此第一个条件需要满足.
7472

75-
对于第二个,由于递归函数子节点的返回值会被父节点使用,因此我们如果两个孩子都选择了
76-
就不符合max path的定义了,这也是我没有理解题意,绕了很大弯子的原因。
73+
对于第二个条件,由于递归函数子节点的返回值会被父节点使用,因此我们如果两个孩子都选择了就不符合 MaxPath 的定义了。实际上这道题,当遍历到某一个节点的时候,我们需要子节点的信息,然后同时结合自身的 val 来决定要不要选取左右子树以及选取的话要选哪一个, 因此这个过程本质上就是`后序遍历`
7774

78-
79-
因此我的做法就是不断调用递归函数,然后在调用过程中不断计算和更新max,最后在主函数中将max返回即可。
75+
基本算法就是不断调用递归函数,然后在调用过程中不断计算和更新 MaxPath,最后在主函数中将 MaxPath 返回即可。
8076

8177
## 关键点解析
8278

@@ -181,6 +177,3 @@ class Solution:
181177
## 相关题目
182178
- [113.path-sum-ii](./113.path-sum-ii.md)
183179

184-
## 扩展
185-
186-
实际上这道题,当遍历到某一个节点的时候,我们需要子节点的信息,然后同时结合自身的 val 来决定要不要选取左右子树。 因此这个过程本质上就是`后序遍历`

problems/1262.greatest-sum-divisible-by-three.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ https://leetcode-cn.com/problems/greatest-sum-divisible-by-three/description/
4444
## 公司
4545

4646
- 字节
47+
- 网易有道
4748

4849
### 思路
4950

@@ -249,3 +250,7 @@ class Solution:
249250
## 扩展
250251

251252
实际上,我们可以采取加法(贪婪策略),感兴趣的可以试一下。
253+
254+
另外如果题目改成了`请你找出并返回能被x整除的元素最大和`,你只需要将我的解法中的 3 改成 x 即可。
255+
256+

problems/198.house-robber.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ class Solution:
203203
- 时间复杂度:$O(N)$
204204
- 空间复杂度:$O(1)$
205205

206+
## 相关题目
207+
208+
- [337.house-robber-iii](https://github.com/azl397985856/leetcode/blob/master/problems/337.house-robber-iii.md)
209+
206210
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 35K star 啦。
207211

208212
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。

problems/62.unique-paths.md

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Output: 28
3838
## 前置知识
3939

4040
- 动态规划
41+
- 排列组合
4142

4243
## 公司
4344

@@ -48,6 +49,12 @@ Output: 28
4849

4950
## 思路
5051

52+
首先这道题可以用排列组合的解法来解,需要一点高中的知识。
53+
54+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1giwviy6wj6j32b80u0792.jpg)
55+
56+
而这道题我们用动态规划来解。
57+
5158
这是一道典型的适合使用动态规划解决的题目,它和爬楼梯等都属于动态规划中最简单的题目,因此也经常会被用于面试之中。
5259

5360
读完题目你就能想到动态规划的话,建立模型并解决恐怕不是难事。其实我们很容易看出,由于机器人只能右移动和下移动,
@@ -57,26 +64,6 @@ Output: 28
5764

5865
代码大概是:
5966

60-
JS Code:
61-
62-
```js
63-
const dp = [];
64-
for (let i = 0; i < m + 1; i++) {
65-
dp[i] = [];
66-
dp[i][0] = 0;
67-
}
68-
for (let i = 0; i < n + 1; i++) {
69-
dp[0][i] = 0;
70-
}
71-
for (let i = 1; i < m + 1; i++) {
72-
for (let j = 1; j < n + 1; j++) {
73-
dp[i][j] = j === 1 ? 1 : dp[i - 1][j] + dp[i][j - 1]; // 转移方程
74-
}
75-
}
76-
77-
return dp[m][n];
78-
```
79-
8067
Python Code:
8168

8269
```python
@@ -104,26 +91,25 @@ class Solution:
10491

10592
当然你也可以使用记忆化递归的方式来进行,由于递归深度的原因,性能比上面的方法差不少:
10693

107-
> 直接暴力递归的话会超时
94+
> 直接暴力递归的话可能会超时
10895
10996
Python3 Code:
11097

11198
```python
11299
class Solution:
113-
visited = dict()
114-
100+
101+
@lru_cache
115102
def uniquePaths(self, m: int, n: int) -> int:
116-
if (m, n) in self.visited:
117-
return self.visited[(m, n)]
118103
if m == 1 or n == 1:
119104
return 1
120105
cnt = self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)
121-
self.visited[(m, n)] = cnt
122106
return cnt
123107
```
124108

109+
125110
## 关键点
126111

112+
- 排列组合原理
127113
- 记忆化递归
128114
- 基本动态规划问题
129115
- 空间复杂度可以进一步优化到 O(n), 这会是一个考点

thinkings/dynamic-programming.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@
44

55
## 递归
66

7-
定义: 递归是指在函数的定义中使用函数自身的方法。
7+
递归是指在函数的定义中使用函数自身的方法。
88

99
算法中使用递归可以很简单地完成一些用循环实现的功能,比如二叉树的左中右序遍历。递归在算法中有非常广泛的使用,包括现在日趋流行的函数式编程。
1010

11-
> 纯粹的函数式编程中没有循环,只有递归
11+
有意义的递归算法会把问题分解成规模缩小的同类子问题,当子问题缩减到寻常的时候,就可以知道它的解。然后建立递归函数之间的联系即可解决原问题,这也是我们使用递归的意义。准确来说, 递归并不是算法,它是和迭代对应的一种编程方法。只不过,由于隐式地借助了函数调用栈,因此递归写起来更简单
1212

13-
有意义的递归算法会把问题分解成规模缩小的同类子问题,当子问题缩写到寻常的时候,我们可以知道它的解。然后我们建立递归函数之间的联系即可解决原问题,这也是我们使用递归的意义。准确来说, 递归并不是算法,它是和迭代对应的一种编程方法。只不过,我们通常借助递归去分解问题而已。
14-
15-
一个问题要使用递归来解决必须有递归终止条件(算法的有穷性),也就是顺递归会逐步缩小规模到寻常。
16-
17-
虽然以下代码也是递归,但由于其无法结束,因此不是一个有效的算法:
13+
一个问题要使用递归来解决必须有递归终止条件(算法的有穷性)。虽然以下代码也是递归,但由于其无法结束,因此不是一个有效的算法:
1814

1915
```py
2016
def f(n):

0 commit comments

Comments
 (0)