mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 03:34:02 +08:00
Update
This commit is contained in:
@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
那么我按照左闭右开的原则,来画一圈,大家看一下:
|
那么我按照左闭右开的原则,来画一圈,大家看一下:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
|
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## 视频讲解
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树](https://www.bilibili.com/video/BV1vW4y1i7dn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
|
|
||||||
## 思路
|
## 思路
|
||||||
|
|
||||||
首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来在切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
|
首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来在切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
|
||||||
|
@ -4,16 +4,6 @@
|
|||||||
</a>
|
</a>
|
||||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||||
|
|
||||||
|
|
||||||
> 递归函数什么时候需要返回值
|
|
||||||
|
|
||||||
相信很多同学都会疑惑,递归函数什么时候要有返回值,什么时候没有返回值,特别是有的时候递归函数返回类型为bool类型。
|
|
||||||
|
|
||||||
那么接下来我通过详细讲解如下两道题,来回答这个问题:
|
|
||||||
|
|
||||||
* 112.路径总和
|
|
||||||
* 113.路径总和ii
|
|
||||||
|
|
||||||
# 112. 路径总和
|
# 112. 路径总和
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/path-sum/)
|
[力扣题目链接](https://leetcode.cn/problems/path-sum/)
|
||||||
@ -29,11 +19,23 @@
|
|||||||
|
|
||||||
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
|
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
|
||||||
|
|
||||||
# 思路
|
## 视频讲解
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和](https://www.bilibili.com/video/BV19t4y1L7CR),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
|
|
||||||
|
## 思路
|
||||||
|
|
||||||
|
相信很多同学都会疑惑,递归函数什么时候要有返回值,什么时候没有返回值,特别是有的时候递归函数返回类型为bool类型。
|
||||||
|
|
||||||
|
那么接下来我通过详细讲解如下两道题,来回答这个问题:
|
||||||
|
|
||||||
|
* 112.路径总和
|
||||||
|
* 113.路径总和ii
|
||||||
|
|
||||||
这道题我们要遍历从根节点到叶子节点的的路径看看总和是不是目标和。
|
这道题我们要遍历从根节点到叶子节点的的路径看看总和是不是目标和。
|
||||||
|
|
||||||
## 递归
|
### 递归
|
||||||
|
|
||||||
可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树
|
可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树
|
||||||
|
|
||||||
@ -57,7 +59,7 @@
|
|||||||
|
|
||||||
所以代码如下:
|
所以代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
bool traversal(treenode* cur, int count) // 注意函数的返回类型
|
bool traversal(treenode* cur, int count) // 注意函数的返回类型
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ bool traversal(treenode* cur, int count) // 注意函数的返回类型
|
|||||||
|
|
||||||
递归终止条件代码如下:
|
递归终止条件代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
|
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
|
||||||
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回
|
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回
|
||||||
```
|
```
|
||||||
@ -168,7 +170,7 @@ public:
|
|||||||
**是不是发现精简之后的代码,已经完全看不出分析的过程了,所以我们要把题目分析清楚之后,在追求代码精简。** 这一点我已经强调很多次了!
|
**是不是发现精简之后的代码,已经完全看不出分析的过程了,所以我们要把题目分析清楚之后,在追求代码精简。** 这一点我已经强调很多次了!
|
||||||
|
|
||||||
|
|
||||||
## 迭代
|
### 迭代
|
||||||
|
|
||||||
如果使用栈模拟递归的话,那么如果做回溯呢?
|
如果使用栈模拟递归的话,那么如果做回溯呢?
|
||||||
|
|
||||||
@ -285,7 +287,7 @@ public:
|
|||||||
|
|
||||||
至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
|
至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
|
||||||
|
|
||||||
# 总结
|
## 总结
|
||||||
|
|
||||||
本篇通过leetcode上112. 路径总和 和 113. 路径总和ii 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。
|
本篇通过leetcode上112. 路径总和 和 113. 路径总和ii 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。
|
||||||
|
|
||||||
|
@ -51,7 +51,13 @@
|
|||||||
|
|
||||||
使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现满足第一种情况的节点,就是最近公共节点了。
|
使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现满足第一种情况的节点,就是最近公共节点了。
|
||||||
|
|
||||||
**但是如果p或者q本身就是最近公共祖先呢?其实只需要找到一个节点是p或者q的时候,直接返回当前节点,无需继续递归子树。如果接下来的遍历中找到了后继节点满足第一种情况则修改返回值为后继节点,否则,继续返回已找到的节点即可。为什么满足第一种情况的节点一定是p或q的后继节点呢?大家可以仔细思考一下。**
|
**但是如果p或者q本身就是最近公共祖先呢**?
|
||||||
|
|
||||||
|
其实只需要找到一个节点是p或者q的时候,直接返回当前节点,无需继续递归子树。
|
||||||
|
|
||||||
|
如果接下来的遍历中找到了后继节点满足第一种情况则修改返回值为后继节点,否则,继续返回已找到的节点即可。
|
||||||
|
|
||||||
|
为什么满足第一种情况的节点一定是p或q的后继节点呢?大家可以仔细思考一下。
|
||||||
|
|
||||||
递归三部曲:
|
递归三部曲:
|
||||||
|
|
||||||
|
@ -198,8 +198,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
* 时间复杂度:$O(n)$,每个节点只遍历了一次
|
* 时间复杂度:O(n),每个节点只遍历了一次
|
||||||
* 空间复杂度:$O(\log n)$,算上递推系统栈的空间
|
* 空间复杂度:O(log n),算上递推系统栈的空间
|
||||||
|
|
||||||
## 总结
|
## 总结
|
||||||
|
|
||||||
|
@ -15,10 +15,11 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
# 思路
|
## 视频讲解
|
||||||
|
|
||||||
**《代码随想录》算法视频公开课:[二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
**《代码随想录》算法视频公开课:[二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
|
## 思路
|
||||||
|
|
||||||
**首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。**
|
**首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。**
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
# 总结
|
## 总结
|
||||||
|
|
||||||
这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。
|
这道题目要求左叶子之和,其实是比较绕的,因为不能判断本节点是不是左叶子节点。
|
||||||
|
|
||||||
@ -174,9 +175,9 @@ public:
|
|||||||
希望通过这道题目,可以扩展大家对二叉树的解题思路。
|
希望通过这道题目,可以扩展大家对二叉树的解题思路。
|
||||||
|
|
||||||
|
|
||||||
# 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
## Java
|
### Java
|
||||||
|
|
||||||
**递归**
|
**递归**
|
||||||
|
|
||||||
@ -245,7 +246,7 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Python
|
### Python
|
||||||
|
|
||||||
**递归后序遍历**
|
**递归后序遍历**
|
||||||
```python
|
```python
|
||||||
@ -291,7 +292,7 @@ class Solution:
|
|||||||
return res
|
return res
|
||||||
```
|
```
|
||||||
|
|
||||||
## Go
|
### Go
|
||||||
|
|
||||||
**递归法**
|
**递归法**
|
||||||
|
|
||||||
@ -342,7 +343,7 @@ func sumOfLeftLeaves(root *TreeNode) int {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## JavaScript
|
### JavaScript
|
||||||
|
|
||||||
**递归法**
|
**递归法**
|
||||||
|
|
||||||
@ -391,7 +392,7 @@ var sumOfLeftLeaves = function(root) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## TypeScript
|
### TypeScript
|
||||||
|
|
||||||
> 递归法
|
> 递归法
|
||||||
|
|
||||||
@ -436,7 +437,7 @@ function sumOfLeftLeaves(root: TreeNode | null): number {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Swift
|
### Swift
|
||||||
|
|
||||||
**递归法**
|
**递归法**
|
||||||
```swift
|
```swift
|
||||||
@ -485,7 +486,7 @@ func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## C
|
### C
|
||||||
递归法:
|
递归法:
|
||||||
```c
|
```c
|
||||||
int sumOfLeftLeaves(struct TreeNode* root){
|
int sumOfLeftLeaves(struct TreeNode* root){
|
||||||
@ -535,7 +536,7 @@ int sumOfLeftLeaves(struct TreeNode* root){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Scala
|
### Scala
|
||||||
|
|
||||||
**递归:**
|
**递归:**
|
||||||
```scala
|
```scala
|
||||||
|
@ -220,9 +220,9 @@ if (count > maxCount) { // 如果计数大于最大值
|
|||||||
```CPP
|
```CPP
|
||||||
class Solution {
|
class Solution {
|
||||||
private:
|
private:
|
||||||
int maxCount; // 最大频率
|
int maxCount = 0; // 最大频率
|
||||||
int count; // 统计频率
|
int count = 0; // 统计频率
|
||||||
TreeNode* pre;
|
TreeNode* pre = NULL;
|
||||||
vector<int> result;
|
vector<int> result;
|
||||||
void searchBST(TreeNode* cur) {
|
void searchBST(TreeNode* cur) {
|
||||||
if (cur == NULL) return ;
|
if (cur == NULL) return ;
|
||||||
|
@ -19,13 +19,18 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
# 思路
|
## 视频讲解
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值](https://www.bilibili.com/video/BV1424y1Z7pn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
|
|
||||||
|
## 思路
|
||||||
|
|
||||||
本地要找出树的最后一行找到最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。
|
本地要找出树的最后一行找到最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。
|
||||||
|
|
||||||
我们依然还是先介绍递归法。
|
我们依然还是先介绍递归法。
|
||||||
|
|
||||||
## 递归
|
### 递归
|
||||||
|
|
||||||
咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?
|
咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?
|
||||||
|
|
||||||
@ -162,7 +167,7 @@ public:
|
|||||||
如果对回溯部分精简的代码 不理解的话,可以看这篇[257. 二叉树的所有路径](https://programmercarl.com/0257.二叉树的所有路径.html)
|
如果对回溯部分精简的代码 不理解的话,可以看这篇[257. 二叉树的所有路径](https://programmercarl.com/0257.二叉树的所有路径.html)
|
||||||
|
|
||||||
|
|
||||||
## 迭代法
|
### 迭代法
|
||||||
|
|
||||||
本题使用层序遍历再合适不过了,比递归要好理解的多!
|
本题使用层序遍历再合适不过了,比递归要好理解的多!
|
||||||
|
|
||||||
@ -194,7 +199,7 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
# 总结
|
## 总结
|
||||||
|
|
||||||
本题涉及如下几点:
|
本题涉及如下几点:
|
||||||
|
|
||||||
@ -204,10 +209,10 @@ public:
|
|||||||
所以本题涉及到的点,我们之前都讲解过,这些知识点需要同学们灵活运用,这样就举一反三了。
|
所以本题涉及到的点,我们之前都讲解过,这些知识点需要同学们灵活运用,这样就举一反三了。
|
||||||
|
|
||||||
|
|
||||||
# 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
|
|
||||||
## Java
|
### Java
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// 递归法
|
// 递归法
|
||||||
@ -264,7 +269,7 @@ class Solution {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Python
|
### Python
|
||||||
|
|
||||||
递归:
|
递归:
|
||||||
```python
|
```python
|
||||||
@ -313,7 +318,7 @@ class Solution:
|
|||||||
return result
|
return result
|
||||||
```
|
```
|
||||||
|
|
||||||
## Go
|
### Go
|
||||||
|
|
||||||
递归法:
|
递归法:
|
||||||
|
|
||||||
@ -373,7 +378,7 @@ func findBottomLeftValue(root *TreeNode) int {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## JavaScript
|
### JavaScript
|
||||||
|
|
||||||
递归版本:
|
递归版本:
|
||||||
|
|
||||||
@ -424,7 +429,7 @@ var findBottomLeftValue = function(root) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## TypeScript
|
### TypeScript
|
||||||
|
|
||||||
> 递归法:
|
> 递归法:
|
||||||
|
|
||||||
@ -469,7 +474,7 @@ function findBottomLeftValue(root: TreeNode | null): number {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Swift
|
### Swift
|
||||||
|
|
||||||
递归版本:
|
递归版本:
|
||||||
|
|
||||||
@ -537,7 +542,7 @@ func findBottomLeftValue(_ root: TreeNode?) -> Int {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Scala
|
### Scala
|
||||||
|
|
||||||
递归版本:
|
递归版本:
|
||||||
```scala
|
```scala
|
||||||
|
@ -41,15 +41,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
```python3
|
|
||||||
class Solution:
|
|
||||||
def sortedSquares(self, nums: List[int]) -> List[int]:
|
|
||||||
res=[]
|
|
||||||
for num in nums:
|
|
||||||
res.append(num**2)
|
|
||||||
return sorted(res)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlog n)。
|
这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlog n)。
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user