牛客网常见算法思路 (七)二叉树

案例一

有用麻烦点个赞哦

递归和非递归方式实现前中后序遍历
递归:比较简单不说了
非递归:
先序
申请一个栈stack,头结点压入stack中,弹出时若右子节点不为空则将右子节点压入栈,再若左子节点不为空则将左子节点压入栈中,不断弹出压入直到结束
中序遍历
申请一个栈stack,申请一个变量cur=head,
2、先将cur压入栈中,然后依次将左边界压入栈中,重复2,直到cur为null;
3、此时弹出node,打印,并将cur=node.right节点,继续重复步骤二
后序遍历
方法一:用两个栈实现
1、申请一个栈s1,头结点压入s1
2、s1弹出的节点记为cur,把cur的左孩子压入s1,然后把cur的右孩子压入s1
3、整个过程中,每个从s1弹出的节点都放进第二个栈s2中
4、不断重复步骤2和3,直到s1为空,过程停止
5、s2中依次弹出节点并打印,打印的顺序是后遍历
方法二:用一个栈实现
1、申请一个栈stack,将头结点压入stack,同时设置变量h和c,整个流程中,h代表最近依次弹出并打印的节点,c代表当前stack栈顶节点,初始是h为头结点c为null
2、每次另c等于当前stack的栈顶节点,但从不stack弹出节点。(1)若c的左孩子不为空,h不等于c的左右孩子(h=c的左右孩子时,说明c的左子树已经打印完毕了),则将c的左孩子压入栈中,(2)情况一不成立,若c的右孩子不为空,h不等于c的右孩子(h=c的右孩子时,说明c的右子树已经打印完毕了),则将c的右孩子压入栈中,(3)若12都不成立(证明左右都打印完毕了),则将c弹出,h=c
3、一直重复步骤2直到stack为空

案例二

二叉树按层遍历,每一层打印完则换行
思想
两个变量last:正在打印的当前行最右节点;nlast:下一行最右节点
遍历到last节点表示要换行,并last=nlast
创建一个队列,从head开始,出队列时将子节点依次放入队列中
nlast一直等于队列中最先加入的节点(必定是下一行的最右节点)

案例三

二叉树序列化和反序列化
之前写过

案例四

判断一棵树是否为平衡二叉树
性质叶子节点深度差不超过1
1、判断左子树是否为平衡二叉树,否则直接返回false
2、左子树最深到哪一层LH
3、右子树是否为平衡二叉树,否则直接返回false
4、右子树最深到哪一层RH
5、对比LH和RH

案例五

判断一棵树是否为搜索二叉树
搜索二叉树,二叉排序树(中序遍历必定是有小到大)
思想:
中序遍历即可,后一个节点小于前一个节点就不是二叉树

案例六

判断一棵树是否为完全二叉树
满二叉树
性质:层数为L,节点数为N,N=(2的L次方)-1,L=log以2为底的N+1
完全二叉树
性质:除最后一层,其他的节点数都是满的(最后一层也满叫满二叉树),若最后一层不满,缺少的节点都在右边,也是完全二叉树
思路
1、层序遍历,从左到右
2、若当前节点有右孩子无左孩子,返回false
3、若当前节点并不是左右孩子全有,之后的节点必须为叶子节点,否则返回false
4、结束后返回true

案例七

新型二叉树节点(多了一个指向父节点的parent指针,头结点的parent指向null)
现只给定二叉树的某个节点node,该节点并不一定是头结点,可能是树的任何一个节点,请实现返回node后继节点的函数
后继节点,一个及诶单的后继节点指这个节点中序遍历的下一个节点(与前驱节点相反)
思路
普通方法
1、通过node节点的parent指针不断向上找到头结点
2、通过找到的头节点,做整棵树的中序遍历,再通过该序列找到node的下一个节点O(N)
最优解
如果node节点和后继节点实际距离为L,则O(L),空间O(1)
1、若node有右子树,直接返回右子树最左边的节点
2、若无右子树,那么先看node是不是父节点的左孩子,是则父节点为后继节点
3、若是右孩子,则寻找向上node,向上移动到的节点记为S,s的父节点为p,若果发现s是p的左孩子,那么p就是node的后继节点,否则向上移动
4、一直向上移动到空节点了还没找到,证明不存在后继节点,返回空

案例八

把一段纸竖着放在桌子上,然后从下方向上对着1次,展开,此时折痕凸起的方向为纸的背面(下折痕)
如果对折两次,此时有三条折痕,从上往下依次为下折痕、下折痕、上折痕
给定参数N,从下向上对着N次,打印折痕方向
思路:
分析得
第一次 下
第二次 上 下
第三次 上 下 上 下
如此类推 …
先右 再中 最后左的遍历

案例九

搜索二叉树,突然出现了两个节点替换,导致不再是搜索二叉树了(顺序被破坏),请找到这两个节点
思路:
1、先中序遍历,出现错误节点会出现降序
2、如果出现了两次降序,第一个错误节点为第一次降序时较大的节点,第二个错误为第二次降序时最小的节点
3、如果出现了一次降序、第一个错误节点为这次比较大的节点、第二个错误为这次比较小的节点

案例十(感觉还是要看代码,之后会更新)

从二叉树节点A出发,可以向上或者乡下走,但沿途的节点只能经过一次,当到达节点b时,路径上的节点数作为A到B的距离,给定一棵二叉树头结点head,求整个书上节点间的最大距离
思路:
最大距离有以下三种情况
情况一:h的左子树上的最大距离
情况二:h的右子树上的最大距离
情况三:h左子树上h孩子最远的距离+h自身+h右子树离h右孩子的最远距离,三者值中最大的就是最大距离
步骤:
1、整个过程为后序遍历,在二叉树的每棵子树上执行步骤2
2、假设子树为头h,处理左子树,得到两个信息,左子树上的最大距离为Lmax1,左子树上距离h左孩子的最远距离为LMax2;处理h右子树得到的右子树上最大距离为RMax1,距离h右孩子的最远距离记为RMax2。嘛呢跨h节点情况下最大距离为Max2+1+RMax2,这个值与LMax1和LMax1相比,比较大的值为最大距离
3、LMax2+1就是h左子树上h最远的点到h的距离,RMax2+1就是h右子树上离h最远的点的距离,选两者中最大的一个作为h树上离h最远的距离返回
4、用返回长度为2的数组方式,可以做的返回两个值

案例十一(建议看代码,之后会更新)

给定一棵二叉树的头结点head,一直其中所有节点的值都不一样,找到含有节点最多的搜索二叉子树,并返回这棵子树的头结点
思路:
遍历节点,node会是以下两种情况
1、node是最大搜索二叉树的节点头:node左子树下的最大搜索二叉子树是以node左孩子为头的,且来自node右子树上的最大搜索二叉子树是以node右孩子为头的,node左子树上最大值小于node,node右子树上的最大搜索二叉子树的最小值大于node
2、不满足第一种情况证明以节点node为头的树整体不能连成搜索二叉树,以node为头的树最大搜索二叉子树来自node左孩子右孩子为头的最大搜索二叉子树中,节点数较多的那个
步骤:
1、整体过程后序遍历
2、遍历到的当前节点即为cur时,先遍历cur的左子树并收集4个信息,分别是左子树上,最大收缩子树的头结点、节点数、树上最小值、最大值;再遍历cur右节点收集这4个信息,分别是右子树上最大搜索二叉子树的头结点、节点数、最小值、最大值
3、根据2收集的信息,判断是否满足情况一,是则返回cur节点,否则返回左右孩子为头的最大搜索二叉树中节点最多的数的头结点

有用麻烦点个赞哦

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值