leetcode-master/problems/二叉树总结篇.md

183 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<p align="center">
<a href="https://programmercarl.com/other/xunlianying.html" target="_blank">
<img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 二叉树:总结篇!(需要掌握的二叉树技能都在这里了)
> 力扣二叉树大总结!
不知不觉二叉树已经和我们度过了**三十三天**[「代码随想录」](https://img-blog.csdnimg.cn/20200815195519696.png)里已经发了**三十三篇二叉树的文章**,详细讲解了**30+二叉树经典题目**,一直坚持下来的录友们一定会二叉树有深刻理解了。
在每一道二叉树的题目中,我都使用了**递归三部曲**来分析题目,相信大家以后看到二叉树,看到递归,都会想:返回值、参数是什么?终止条件是什么?单层逻辑是什么?
而且**几乎每一道题目我都给出对应的迭代法**,可以用来进一步提高自己。
下面Carl把分析过的题目分门别类可以帮助新录友循序渐进学习二叉树也方便老录友面试前快速复习看到一个标题就回想一下对应的解题思路这样很快就可以系统性的复习一遍二叉树了。
公众号的发文顺序,就是循序渐进的,所以如下分类基本就是按照文章发文顺序来的,我再做一个系统性的分类。
## 二叉树的理论基础
* [关于二叉树,你该了解这些!](https://programmercarl.com/二叉树理论基础.html):二叉树的种类、存储方式、遍历方式、定义方式
## 二叉树的遍历方式
* 深度优先遍历
* [二叉树:前中后序递归法](https://programmercarl.com/二叉树的递归遍历.html):递归三部曲初次亮相
* [二叉树:前中后序迭代法(一)](https://programmercarl.com/二叉树的迭代遍历.html):通过栈模拟递归
* [二叉树:前中后序迭代法(二)统一风格](https://programmercarl.com/二叉树的统一迭代法.html)
* 广度优先遍历
* [二叉树的层序遍历](https://programmercarl.com/0102.二叉树的层序遍历.html):通过队列模拟
## 求二叉树的属性
* [二叉树:是否对称](https://programmercarl.com/0101.对称二叉树.html)
* 递归:后序,比较的是根节点的左子树与右子树是不是相互翻转
* 迭代:使用队列/栈将两个节点顺序放入容器中进行比较
* [二叉树:求最大深度](https://programmercarl.com/0104.二叉树的最大深度.html)
* 递归:后序,求根节点最大高度就是最大深度,通过递归函数的返回值做计算树的高度
* 迭代:层序遍历
* [二叉树:求最小深度](https://programmercarl.com/0111.二叉树的最小深度.html)
* 递归:后序,求根节点最小高度就是最小深度,注意最小深度的定义
* 迭代:层序遍历
* [二叉树:求有多少个节点](https://programmercarl.com/0222.完全二叉树的节点个数.html)
* 递归:后序,通过递归函数的返回值计算节点数量
* 迭代:层序遍历
* [二叉树:是否平衡](https://programmercarl.com/0110.平衡二叉树.html)
* 递归:后序,注意后序求高度和前序求深度,递归过程判断高度差
* 迭代:效率很低,不推荐
* [二叉树:找所有路径](https://programmercarl.com/0257.二叉树的所有路径.html)
* 递归:前序,方便让父节点指向子节点,涉及回溯处理根节点到叶子的所有路径
* 迭代:一个栈模拟递归,一个栈来存放对应的遍历路径
* [二叉树:递归中如何隐藏着回溯](https://programmercarl.com/二叉树中递归带着回溯.html)
* 详解[二叉树:找所有路径](https://programmercarl.com/0257.二叉树的所有路径.html)中递归如何隐藏着回溯
* [二叉树:求左叶子之和](https://programmercarl.com/0404.左叶子之和.html)
* 递归:后序,必须三层约束条件,才能判断是否是左叶子。
* 迭代:直接模拟后序遍历
* [二叉树:求左下角的值](https://programmercarl.com/0513.找树左下角的值.html)
* 递归:顺序无所谓,优先左孩子搜索,同时找深度最大的叶子节点。
* 迭代:层序遍历找最后一行最左边
* [二叉树:求路径总和](https://programmercarl.com/0112.路径总和.html)
* 递归顺序无所谓递归函数返回值为bool类型是为了搜索一条边没有返回值是搜索整棵树。
* 迭代:栈里元素不仅要记录节点指针,还要记录从头结点到该节点的路径数值总和
## 二叉树的修改与构造
* [翻转二叉树](https://programmercarl.com/0226.翻转二叉树.html)
* 递归:前序,交换左右孩子
* 迭代:直接模拟前序遍历
* [构造二叉树](https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html)
* 递归:前序,重点在于找分割点,分左右区间构造
* 迭代:比较复杂,意义不大
* [构造最大的二叉树](https://programmercarl.com/0654.最大二叉树.html)
* 递归:前序,分割点为数组最大值,分左右区间构造
* 迭代:比较复杂,意义不大
* [合并两个二叉树](https://programmercarl.com/0617.合并二叉树.html)
* 递归:前序,同时操作两个树的节点,注意合并的规则
* 迭代:使用队列,类似层序遍历
## 求二叉搜索树的属性
* [二叉搜索树中的搜索](https://programmercarl.com/0700.二叉搜索树中的搜索.html)
* 递归:二叉搜索树的递归是有方向的
* 迭代:因为有方向,所以迭代法很简单
* [是不是二叉搜索树](https://programmercarl.com/0098.验证二叉搜索树.html)
* 递归:中序,相当于变成了判断一个序列是不是递增的
* 迭代:模拟中序,逻辑相同
* [求二叉搜索树的最小绝对差](https://programmercarl.com/0530.二叉搜索树的最小绝对差.html)
* 递归:中序,双指针操作
* 迭代:模拟中序,逻辑相同
* [求二叉搜索树的众数](https://programmercarl.com/0501.二叉搜索树中的众数.html)
* 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
* [二叉搜索树转成累加树](https://programmercarl.com/0538.把二叉搜索树转换为累加树.html)
* 递归:中序,双指针操作累加
* 迭代:模拟中序,逻辑相同
## 二叉树公共祖先问题
* [二叉树的公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)
* 递归:后序,回溯,找到左子树出现目标值,右子树节点目标值的节点。
* 迭代:不适合模拟回溯
* [二叉搜索树的公共祖先问题](https://programmercarl.com/0235.二叉搜索树的最近公共祖先.html)
* 递归:顺序无所谓,如果节点的数值在目标区间就是最近公共祖先
* 迭代:按序遍历
## 二叉搜索树的修改与构造
* [二叉搜索树中的插入操作](https://programmercarl.com/0701.二叉搜索树中的插入操作.html)
* 递归:顺序无所谓,通过递归函数返回值添加节点
* 迭代:按序遍历,需要记录插入父节点,这样才能做插入操作
* [二叉搜索树中的删除操作](https://programmercarl.com/0450.删除二叉搜索树中的节点.html)
* 递归:前序,想清楚删除非叶子节点的情况
* 迭代:有序遍历,较复杂
* [修剪二叉搜索树](https://programmercarl.com/0669.修剪二叉搜索树.html)
* 递归:前序,通过递归函数返回值删除节点
* 迭代:有序遍历,较复杂
* [构造二叉搜索树](https://programmercarl.com/0108.将有序数组转换为二叉搜索树.html)
* 递归:前序,数组中间节点分割
* 迭代:较复杂,通过三个队列来模拟
## 阶段总结
大家以上题目都做过了,也一定要看如下阶段小结。
**每周小结都会对大家的疑问做统一解答,并且对每周的内容进行拓展和补充,所以一定要看,将细碎知识点一网打尽!**
* [本周小结!(二叉树系列一)](https://programmercarl.com/周总结/20200927二叉树周末总结.html)
* [本周小结!(二叉树系列二)](https://programmercarl.com/周总结/20201003二叉树周末总结.html)
* [本周小结!(二叉树系列三)](https://programmercarl.com/周总结/20201010二叉树周末总结.html)
* [本周小结!(二叉树系列四)](https://programmercarl.com/周总结/20201017二叉树周末总结.html)
## 最后总结
**在二叉树题目选择什么遍历顺序是不少同学头疼的事情我们做了这么多二叉树的题目了Carl给大家大体分分类**
* 涉及到二叉树的构造,无论普通二叉树还是二叉搜索树一定前序,都是先构造中节点。
* 求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。
* 求二叉搜索树的属性,一定是中序了,要不白瞎了有序性了。
注意在普通二叉树的属性中,我用的是一般为后序,例如单纯求深度就用前序,[二叉树:找所有路径](https://programmercarl.com/0257.二叉树的所有路径.html)也用了前序,这是为了方便让父节点指向子节点。
所以求普通二叉树的属性还是要具体问题具体分析。
二叉树专题汇聚为一张图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211030125421.png)
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
**最后二叉树系列就这么完美结束了估计这应该是最长的系列了感谢大家33天的坚持与陪伴接下来我们又要开始新的系列了「回溯算法」**
## 其他语言版本
Java
Python
Go
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>