LeetCode236 二叉树的最近公共祖先

40 阅读1分钟

leetcode.cn/problems/lo…

image.png

解法一:基于分解子问题思维模式的递归

祖先的定义:  若节点 p 在节点 root 的左(右)子树中,或 p=root ,则称 root 是 p 的祖先。

image.png

最近公共祖先的定义: 设节点 root 为节点 p,q 的某公共祖先,若其左子节点 root.left 和右子节点 root.right 都不是 p,q 的公共祖先,则称 root 是 “最近的公共祖先”。

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

  • p 和 q 在 root 的子树中,且分列 root 的 异侧(即分别在左、右子树中);
  • p=root ,且 q 在 root 的左或右子树中;
  • q=root ,且 p 在 root 的左或右子树中;
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    // base case
    if root == nil{ // 越过叶子节点都没找到答案
        return nil
    }
    if root == p || root == q { // p和q中刚好有等于root的
        return root
    }
    // 在左、右子树中寻找二者最近公共祖先
    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)
    if left == nil && right == nil{ // case1: 左右子树都不包含p, q,且前面判断也不等于root,找不到公共祖先
        return nil
    }
    if left != nil && right != nil{ // case2: 说明一个处于左子树,一个处于右子树,直接返回根节点
        return root
    }
    if left != nil{ // case3: right = nil, p, q都在左子树中,返回递归找到的二者最近公共祖先
        return left
    }
    // case4: left = nil, p, q都在右子树中,返回递归找到的二者最近公共祖先
    return right
}