二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1输出:3解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4输出:5解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2输出:1
思路:
这一题我们就用递归来做。定义寻找公共祖先函数 lowestCommonAncestor,我们已知它的功能很明确:传入根节点root和两个节点p和q,返回这两个节点的最小公共祖先。
直接说思路吧:我们从最外层的视角审视这个递归,传入的是根节点、结点p、结点q,假设节点p和节点q分别在根节点的左右两处,那么根节点就是两者的最小公共祖先;假设p和q都在根节点的左子树,则我们送入递归(根节点的左子树,节点p,节点q)就好了,让它更进一步;假设p和q都在根节点的右子树,则我们送入递归(根节点的右子树,节点p,节点q);假设根节点下既没有q也没有q,则肯定不合理,返回None。
但是还有一种情况我们没有考虑到,我们把它作为base case。这种情况是:假设根节点下只有q或只有p,则这个节点在哪个子树,就更进一步送入递归。比如只有根节点的右子树有个q,则送入递归(根节点的右子树,节点p,节点q)即可。因为这种情况下,我们是找不到p和q的公共祖先的,我们只需要最后把根节点逼近到它包含的p或q节点,然后返回这个根节点即可。所以针对这种情况还有一个base case:假设根节点等于p或q,直接返回当前根节点。Base case部分也就定义好了。
虽然具体逻辑和base case可以讲得很明白,但是代码里巧妙地将这些思路进行了一个整合,所以上面的思路大概理解即可,不要逐一去对照代码来看,代码写得更加简洁:
代码:
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
if not root:#处理一下特殊情况之类的
return
if root==p or root==q:#base case,如果root等于p或q了
return root#直接返回当前root
left_res = self.lowestCommonAncestor(root.left,p,q)#递归去寻找root.left
right_res = self.lowestCommonAncestor(root.right,p,q)#递归root.right
if left_res and right_res:#假如左右两边都有,则root就是公共祖先
return root
if left_res:#假如只有左边有——不管是“左边有p和q”还是“左边有p或q”
return left_res#交给root.left的递归即可
if right_res:#假如只有右边有,同理
return right_res
return None#假如左右两边都找不到,则返回None
小结:
虽然我们可以把具体情况罗列得很详细分明,但实际的代码还是把部分功能糅杂在一起了,所以看起来不是清晰,但知道思路之后,应该也感觉到这样写的巧妙之处吧。
最后感觉再梳理一下我们处理的情况和思路:
- 假如root的左边包含q,右边包含q;或者左边包含q,右边包含p,即一边一个,则直接返回root。这种情况没问题吧,也就是我们唯一找到目标节点的情况。
- 假如root下既不包含p也不包含q,则返回None。
- 假设root左子树同时包含p和q,则返回root.left的递归。
- 假设root的右子树同时包含p和q,则返回root.right的递归。
- 假如root下只包含p(不管左还是右),则送入root.left或root.right的递归,最终通过递归到情况7返回p节点。
- 假如root下只包含q(不管左还是右),则送入root.left或root.right的递归,最终通过递归到情况7则返回q节点。
- 假设root等于q或p,直接返回root。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了