二叉树题目汇总

本文汇总了关于二叉树的各种常见题目,包括前序、中序、后序遍历,层次遍历,求结点数、叶子数、特定层结点数、树的深度,判断两树结构相同、镜像,最低公共祖先,两结点距离,祖先结点,平衡二叉树,路径和,重建二叉树,以及二叉搜索树与双向链表的转换。强调了画图和边界测试在解题中的重要性。
摘要由CSDN通过智能技术生成

内容会持续更新,有错误的地方欢迎指正,谢谢!

前言

宏观概念:有向图 可退化为 树 可退化为 链表
二叉树虽然简单,但是与链表相比,树的题目涉及到大量指针,细微之处更能特别考验程序员的能力,所以,若想加大面试难度,树的题目是不二之选,博主在此列出一些二叉树常见的题型。

思路:只有画出二叉树的图+具体的例子(一边看着图形一边讲解,面试官会更轻松地理解你的思路,并觉得你好沟通),才好找出题目的规律,才好发现错误和漏洞,才好设计出可行的算法。也就是,先想(讲)清楚思路,得到肯定后,再码代码!
注意:先考虑边界测试:每一次需要访问地址的时候都要问自己这个地址有没有可能是nullptr,如果是nullptr那怎么处理;再考虑功能测试:完全二叉树和非完全二叉树。
用递归实现的话,边界测试一般需要以下判断:

    if(pRoot==nullptr)
        return;//return 0; 或return nullptr;

小套路:如果递归函数为bool型,则双重递归函数要么在if中,要么就在return中。例子:

if(Func(pRoot->left)&&Func(pRoot->right))
    return true;
return false;
//等价于:
return Func(pRoot->left)&&Func(pRoot->right);
//但是,第一种可以加一些处理操作:
if(Func(pRoot->left)&&Func(pRoot->right))
{
    //可以加一些cout用于输出,或者加一些if用于判断是否返回true等等
    return true;
}
return false;

目录

1、前序遍历,中序遍历,后序遍历

法一:递归实现(其实递归就是一种栈)
法二:栈+迭代

2、层次遍历

宽度优先搜索BFS,迭代,使用先进先出的队列queue或两端都可以进出的deque,要让队列有进有出。

3、求树的结点数

遍历。return 1+左子树的个数+右子树的个数

4、求树的叶子数

遍历。return 左子树的叶结点数+右子树的叶结点数

5、求二叉树第k层的结点个数

遍历。k作为递归函数的参数,每降低一层,k就要-1。
return KNodeCount(pRoot->left,k-1)+KNodeCount(pRoot->right,k-1);
13题(二叉树中和为某一值的路径)的思路和该题很像。

6、求树的深度

遍历。对根结点求深度,就是求其左右子树的深度中最大的那个深度+1

7、判断两颗二叉树是否结构相同

(不用考虑val是否相同。结构相同:两颗二叉树的两个根结点对应的的左子树和右子树结构相同。)
遍历。return 判断两棵树的左子树是否相同&&判断两棵树的右子树是否相同;
什么叫相同?两个对应的结点同时为空
什么叫不同?两个对应的结点中只有一个结点为空
那都不为空时呢?去递归呗。

8、求二叉树的镜像(又叫翻转二叉树)

遍历。对于根结点,交换其左右子树,左右子树各自去递归。

补充的问题:判断是不是对称的二叉树。方法:bool函数,前序遍历,对应的结构和对应的值都要相等,return里 左右子树继续去递归。

小窍门:该类问题很抽象,图形能使抽象的问题具体化、形象化,得到规律。比如:二叉树、链表、二维数组等问题都可以采用画图的方法来分析。空想很难能想明白题目中隐含的规律。

9、求两个结点的最低公共祖先结点

题目1:若这是一棵二叉查找树,那么就简单了:1.当根结点的值大于两个这结点的值,则继续在左子树中找;2.当根结点的值小于两个这结点的值,则继续在右子树中找;3.当根结点的值在这两个结点的值之间,则该根结点就是最低公共祖先结点。
题目2:若这不是一棵二叉树,只是普通的树,每个结点除了根结点外 都有指向父结点的指针:这不就是求两个链表的第一个公共结点嘛。
题目3:就是下方的第9题,若这是一颗二叉树(题目偏难),则遍历后,需有如下判断:

//对一个根结点来说,分别在左右子树中找到了目标结点,则该根结点就是所求结点。
if (left!=nullptr && right!=nullptr)
    return pRoot;
//对一个根结点来说,只在左子树或右子树找到了目标结点,则返回找到的结点。
return left!=nullptr ? left : right;
10、求任意两结点距离

遍历。先找到两个结点的最低公共祖先结点,然后分别计算最低公共祖先结点(根结点)与它们的距离,最后相加即可。也就是两个函数,第二个函数用于求距离:遍历,先在左子树中找,if没找到的话,再在右子树中找,找到了则return res+1;最后都没找到就return -1。

11、找出二叉树中某个结点的所有祖先结点

遍历。bool递归函数。if(找出该结点的左子树中某个结点的所有祖先结点||找出该结点的右子树。。。),如果为if条件为true,则输出该结点。

12、判断二叉树是否是平衡二叉树(了解)

遍历。if(判断左子树是否是平衡二叉树&&判断右子树是否是平衡二叉树),再在这个if中,if(判断深度差left-right的绝对值是否小于1)。。。挺有挑战的一道题。

13、二叉树中和为某一值的路径

前序遍历,和expectNumber作为递归函数的一个参数,每降低一层,expectNumber就要减去刚才那个结点的值。
定义一个二维vector容器res和一个一维vector容器temp。每路过一个结点,就将该结点装进temp。若走到了叶节点,且该条路的和刚好等于expectNumber,则将这条路(temp记录的)装入res;若此时和不等于expectNumber,就回溯。
如何回溯?
在双重递归后加上temp.pop_back() 弹出最后那个元素,再装入下一个要遍历的元素,不就好了。

14、根据前序和中序重建二叉树

构建 左子树的前序中序 和 右子树的前序中序,再分左右子树递归。
小窍门:当我们发现大问题和小问题在本质上是一致时,便可用递归解决,所以二叉树的题基本都用递归。由于要遍历二叉树,所以基本都用双重递归。

15、二叉搜索树与双向链表

中序遍历。简单题。定义两个变量,一个变量用于记录头结点,一个变量用于改变指向。
小窍门:一定要先画图分析,通过分析得到思路后,再动手写代码,不要一开始就写,不然越写越懵。

1、前序遍历,中序遍历,后序遍历

要么用递归(递归其实就是栈的思想),要么就用栈+迭代。
其实,其他题目都是在间接地考察这三种遍历,尤其是前序遍历考得多。所以,该题是核心。

前序遍历-根左右
  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值