【Leetocode 236. 二叉树的最近公共祖先】

题目

Leetocode 236. 二叉树的最近公共祖先

思路

采用递归的思路假定当前函数一定能找到最近公共祖先的候选者(允许为空)
本质上,该题目有三种情况,情况1:两个节点p,q分布于最深父公共祖先(LCA)的两侧。情况2:两个节点中的较浅节点p就为LCA,此时另一个节点q在该节点之下。情况三:子树中没有p,q,则返回空节点

接下来,我们从自底向上的视角理解。

首先确定返回值。当递归到某个节点,该节点符合(root == p or root == q)的条件就向上返回,这个节点是一个潜在的LCA候选者(Candidate)。候选者的意思是它有可能就是我们在找的LCA,也有可能并不是,但是和None不一样,它是有用的。当递归到None,也向上返回,说明该侧已经搜寻完毕,不可能存在任何候选者。

情况1的对应: 该Candidate向上返回到某个节点Node,发现如果另一侧也返回了一个Candidate。说明Node才是真正的LCA。

情况2的对应:该Candidate向上返回时,一路畅通无阻(另一侧始终是None),一直返回到根节点。说明刚刚的Candidate即为在寻找的LCA。(即p, q都在这一分支上)

情况3的对应:两边都没找到候选者;返回空节点(比如p,q都在右子树;此时访问左子树的时候他就会返回空节点)

代码(26.4.29首刷)

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil || root == p || root == q {
        return root
    }
    // 假设左右子树都有公共祖先候选者(若两侧都不为空,则当前根节点即为最近公共祖先;若一侧为空,则p,q都在另一侧;若都为空,则代表没有候选者)
    leftLca := lowestCommonAncestor(root.Left, p, q)
    rightLca := lowestCommonAncestor(root.Right, p, q)
    if leftLca != nil && rightLca != nil {
        return root
    }
    if leftLca != nil {
        return leftLca
    }
    if rightLca != nil {
        return rightLca
    }
    return nil
}

相似题目

二叉搜索树的公共祖先

思路

这一题相较于上一题;可以通过二叉搜索树的性质;判断p,q与当前节点的大小关系;来确定p,q所处的左右子树。
题目保证p,q一定存在,那就只能三种情况:

  1. p,q都小于x,返回左子树就行
  2. p,q都大于x,访问右子树就行
  3. p, q 在x的两侧,此时直接返回x就行

代码

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
	x := root.Val
    // 都在左子树上
    if p.Val < x && q.Val < x {
        return lowestCommonAncestor(root.Left, p, q)
    }

    // 都在右子树上
    if p.Val > x && q.Val > x {
        return lowestCommonAncestor(root.Right, p, q)
    }

    // 左右子树都有; 左右子树都没有的情况不需要讨论; 题目保证一定存在p,q
    return root
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值