解法一:基于分解子问题思维模式的递归
祖先的定义: 若节点 p 在节点 root 的左(右)子树中,或 p=root ,则称 root 是 p 的祖先。
最近公共祖先的定义: 设节点 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
}