236.Lowest Common Ancestor of a Binary Tree

25 年 7 月 13 日 星期日
1241 字
7 分钟

236. Lowest Common Ancestor of a Binary Tree

js
/**
 * 寻找二叉树中两个节点的最近公共祖先
 * @param {TreeNode} root - 二叉树的根节点
 * @param {TreeNode} p - 目标节点1
 * @param {TreeNode} q - 目标节点2
 * @returns {TreeNode} 最近公共祖先节点
 */
function lowestCommonAncestor(root, p, q) {
  // 递归终止条件:
  // 1. 遍历到空节点(说明当前路径没有找到p/q)
  // 2. 找到p节点或q节点(直接返回该节点,作为找到的标记)
  if (root === null || root === p || root === q) {
    return root
  }

  // 递归遍历左子树,寻找p或q
  const left = lowestCommonAncestor(root.left, p, q)
  // 递归遍历右子树,寻找p或q
  const right = lowestCommonAncestor(root.right, p, q)

  // 情况1:左子树和右子树都没找到p/q,说明当前节点的子树中无目标节点,返回null
  if (left === null && right === null) {
    return null
  }

  // 情况3:左子树没找到,右子树找到了,说明p/q都在右子树中,返回右子树找到的节点
  if (left === null) {
    return right
  }

  // 情况4:右子树没找到,左子树找到了,说明p/q都在左子树中,返回左子树找到的节点
  if (right === null) {
    return left
  }

  // 情况2:左子树和右子树都找到了目标节点(一个在左、一个在右)
  // 说明当前root就是最近公共祖先,返回root
  return root
}

问:lowestCommonAncestor 函数的返回值是什么意思?

答:返回值的准确含义是「最近公共祖先的候选项」。对于最外层的递归调用者来说,返回值是最近公共祖先的意思。但是,在递归过程中,返回值可能是最近公共祖先,也可能是空节点(表示子树内没找到任何有用信息)、节点 p 或者节点 q(可能成为最近公共祖先,或者用来辅助判断上面的某个节点是否为最近公共祖先)。

作者:灵茶山艾府 链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/solutions/2023872/fen-lei-tao-lun-luan-ru-ma-yi-ge-shi-pin-2r95/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

根据以上定义,若 root 是 p,q 的 最近公共祖先 ,则只可能为以下情况之一:

  1. p 和 q 在 root 的子树中,且分列 root 的 异侧(即分别在左、右子树中);
  2. p=root ,且 q 在 root 的左或右子树中;
  3. q=root ,且 p 在 root 的左或右子树中;

二叉树最近公共祖先——递归解析

思路
通过递归对二叉树进行先序遍历,当遇到节点 pq 时返回。从底至顶回溯,当 p, q 在当前节点 root 的异侧时,root 即为最近公共祖先,向上返回 root

1. 终止条件

  • 越过叶节点
    • root == null 时,直接返回 null
  • 找到目标节点
    • root == proot == q 时,直接返回 root

2. 递推工作

  1. 递归调用左子树,返回值记为 left
  2. 递归调用右子树,返回值记为 right

3. 根据 leftright 的情况返回结果

  1. leftright 同时为空
    • 说明 root 的左右子树都不包含 p, q
    • 返回 null
  2. leftright 同时不为空
    • 说明 p, q 分别在 root 的左、右子树
    • 因此当前 root 就是最近公共祖先,返回 root
  3. left 为空,right 不为空
    • 说明 p, q 不在 root 的左子树中,直接返回 right
    • 细分两种情况:
      1. 只有 pq(假设为 p)在右子树,此时 right 指向 p
      2. p, q 都在右子树,此时 right 指向它们的最近公共祖先
  4. left 不为空,right 为空
    • 同理,说明 p, q 都不在右子树,直接返回 left

作者:Krahets 链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/solutions/240096/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 只要当前根节点是p和q中的任意一个,就返回(因为不能比这个更深了,再深p和q中的一个就没了)
        if not root or root == p or root == q:
            return root
        # 根节点不是p和q中的任意一个,那么就继续分别往左子树和右子树找p和q
        # left和right为 p 或者 q 或者 None
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        # p和q都没找到,那就没有
        if left == None and right == None:
            return None
        # 左子树没有p也没有q,就返回右子树的结果
        if left == None:
            return right
        # 右子树没有p也没有q就返回左子树的结果
        if right == None:
            return left
        # 左右子树都找到p和q了,那就说明p和q分别在左右两个子树上,所以此时的最近公共祖先就是root
        return root

文章标题:236.Lowest Common Ancestor of a Binary Tree

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/236lowest_common_ancestor_of_a_binary_tree[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。