(四) 二叉树问题
1、 二叉树的前中后序遍历
- DFS(递归)
- 设一个void的遍历函数,设一个主函数
2、 二叉树的层序遍历:
-
BFS(迭代)。用队列实现,每次记录下当前队列的大小即可。
-
递归:递归函数功能:遍历当前层depth的所有结点并收集结果到list;
3、 给定一个二叉树,返回该二叉树的之字形层序遍历
- 队列+数组
if (level % 2 == 0) {
// 从左至右打印
arr.push_back(tmp->val);
}
else {
// 从右至左打印
arr.insert(arr.begin(), tmp->val);
}
4、 二叉树的最大深度
- 递归,不用另外设DFS函数
5、 给定一个二叉树root和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径
- 递归,不用另外设DFS函数
6、 给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
- 递归
7、 合并二叉树
- 递归
8、 操作给定的二叉树,将其变换为源二叉树的镜像
9、 判断是不是完全二叉树
- 将每层的节点以层序遍历的方式全部放入队列中(包括null) 如果是完全二叉树,在我们取出节点的时候,应该是直到整棵树遍历完毕才会遇到null。
- 所以当我们按层序遍历的方式,遇到null,但是队列中仍然存在节点,则代表不是完全二叉树;否则,是完全二叉树。
- 首先每个节点都会有4种情况,开始寻找规律:
- 1:如果当前访问的节点的左右孩子是情况3,说明不是完全二叉树,直接返回false。
- 2:如果当前访问的节点的左右孩子是情况1,继续访问其他节点。
- 3:如果当前访问的节点的左右孩子是情况2或者情况4,那么我们定义一个状态(接下来访问的所有节点必须全部是叶子节点)。只要遇到情况2或者情况4,这个状态就开启了
10、判断是不是平衡二叉树
11、 序列化二叉树:实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树
- 二叉树的序列化(Serialize)是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树等遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#)
- 二叉树的反序列化(Deserialize)是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
12、 重建二叉树:给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点
13、 输出二叉树的右试图
- 根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图
(五)二叉搜索树的问题
1、 给定一棵二叉搜索树,请找出其中第 k 大的节点的值
- 递归,求出二叉树的中序倒序,然后取第k个数;因为是中序,所以会在调用两次函数中间进行操作。
2、 计算二叉树的深度,判断是不是平衡二叉树
- 递归,求出二叉树的后序遍历;
- 左右子树的最大值+1
3、 判断是不是二叉搜索树
- 中序遍历,是否递增
4、 判断是不是完全二叉树:
- 完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
5、 最近公共祖先
(1)二叉搜索树的最近公共祖先
- 递归。迭代
(2) 二叉树的最近公共祖先
- 递归,后序遍历
(3)这两道题的重点在于判断何时开始递归。
- 对于二叉搜索树来说,分三种情况:
- (1)p、q一个比root大,一个比root小,则p、q分别在左右两子树,公共祖先是root。
- (2)当 p, q都在 rootroot 的 右子树 中,则开启递归 root.right
- (3)当 p, q 都在 rootroot 的 左子树 中,则开启递归 root.left并返回。
- 对于二叉树来说,分为四种情况:
- (1)当 left和 right 同时为空 :说明 root的左 / 右子树中都不包含 p,q ,返回 null ;
- (2)当 left和 right同时不为空 :说明 p, q 分列在 root的 异侧 (分别在 左 / 右子树),因此 root 为最近公共祖先,返回 root;
- (3)当 left为空 ,right不为空 :p,q都不在 root 的左子树中,直接返回 right 。
- (4)当 left不为空 , right为空 :与情况 3. 同理;(终止条件:到子节点或者root 等于 p, q)
6、 求二叉树两个节点(a,b)的距离
- 计算
dis(root,a)+dis(root,b)-2*dis(root,lca) (lca为a和b的最小公共祖先)
7、 一个二叉树是否为另一个的子树
- 递归
8、 给定前中序重建二叉树
- 递归
9、 两棵树的最大公共子树
- dfs
10、 二叉搜索树的后序遍历序列
- 递归
11、 将该二叉搜索树转换成一个排序的循环双向链表
- 二叉搜索树的中序遍历为 递增序列
- 排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点。
- 双向链表: 在构建相邻节点的引用关系时,设前驱节点 pre 和当前节点 cur ,不仅应构建
pre.right = cur
,也应构建cur.left = pre
。 - 循环链表: 设链表头节点 head 和尾节点 tail ,则应构建
head.left = tail
和tail.right = head
。
12、 跳跃游戏
- 如果一个位置能够到达,那么这个位置左侧所有位置都能到达
13、 给n个数,可以构造多少个不同的二叉树
- 动态规划
14、 验证二叉搜索树
- 递归