二叉树的最近公共祖先

在这里插入图片描述

二叉树的最近公共祖先

在这里插入图片描述
难度 中等 题目链接

题目说明
在这里插入图片描述
从上图可以发现,公共祖先的结论:一个在我左边,一个在我右边。我就是公共祖先还有一个特殊情况:
在这里插入图片描述
如果有一个是另一个的祖先,那么自己就是公共祖先

方法一

首先,我们需要写一个函数来判断p和q是否在树中:
在这里插入图片描述
我们需要判断根是不是其中的p或者q。如果不是我们要去判断在不在的左子树和右子树的一个情况。
在这里插入图片描述
然后对pInLeft,pInRight,qInRight,qInLeft进行判断分析。
在这里插入图片描述
如果在同一边,我们就递归到一边去找。

完整代码
在这里插入图片描述
但是这样的写法,它的时间复杂度不是特别好。
在这里插入图片描述
如果是这样的二叉树,那么它第一次N,第二次是N-1,第三次是N-2,… …所以时间复杂度是O(N^2),它由于会递归N次,所以空间复杂度是O(N)。

方法二

利用栈来记录p和q结点到root结点的路径,然后转换成相交问题
在这里插入图片描述
首先,先让结点入栈,然后判断此结点是否是q。不是,我们先递归左子树。
在这里插入图片描述
还是同样的道理,先把5入进去再判断。不能先判断,原因如果不是结点5不入进去就找不到下面的结点了。
在这里插入图片描述
当来到6的时候,6不是q,左子树为空,返回。递归到右子树,右子树为空,返回。说明6不是q结点路径上的一员,所以6要出栈。
在这里插入图片描述
那么5的左子树就递归完了,开始走5的右子树。
在这里插入图片描述
来到7的时候和6的时候一样,左子树,右子树都为空,7也不是q,所以7出栈。2的左子树递归结束没找到,去2的右子树找。
在这里插入图片描述
q找到了,那么就可以返回true了。此时栈里的数据就是路径。
在这里插入图片描述
此时,两个栈中都存放了自己的路径。
在这里插入图片描述
我们就可以转换成相交的问题。让长的先pop掉差距,然后比较相等的结点。
在这里插入图片描述

方法三

方法三我们用递归套路来做,首先我们分析可能性:假设一个结点为x,我们要找p,q结点的最近公共祖先。

第一种情况:x不是最近公共祖先
1. 最近公共祖先在x的左子树或者右子树。
2. p,q不在以x为根结点的树中

第二种情况:x是最近公共祖先
1. x是p或q中的一个。
2. p,q其中一个在左子树,另外一个在右子树

分析可能性之后,我们就可以列信息体了。
根据情况的分析,我们需要:
1.p,q是否在以x为根结点的树中。
2.最近公共祖先是否在以x为根结点的树中

在这里插入图片描述
然后写为空和不为空的情况:
在这里插入图片描述
当递归回来的时候,我们需要写自己的信息:
在这里插入图片描述
最后返回结果:
在这里插入图片描述

方法四

方法四我们可以使用容器来做。
解决思路:
1.定义一个map一个存当前结点,一个存当前结点的父结点。
在这里插入图片描述
然后将根结点和它的父结点存到map中。

2.写一个前序遍历把整棵树的孩子结点和父结点相对应。
在这里插入图片描述
在这里插入图片描述

3.定义一个set把p存进去,然后把p的所有祖先都存进去。
在这里插入图片描述
4.在set里面去找q,如果没找到就在map里找它的父结点,一直在set找到,此时结点就是最近公共祖先。
在这里插入图片描述

代码实现:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学代码的咸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值