对于二叉树中任意两个结点p和q,可能存在如下的情形:
- p是q的祖先,此时p是p和q的最近公共祖先
- q是p的祖先,此时q是p和q的最近公共祖先
- p和q没有父子关系。
如果设p和q的最近公共祖先为x。如果x是p和q的公共祖先(不一定是最近的),应该会满足如下条件:
- x == p,且x的左子树或右子树包含结点q
- x== q,且x的左子树或右子树包含结点p
- x的左子树包含结点q,且右子树包含结点p或相反。
考虑采用后续遍历来确定最近公共祖先。
- 当遍历到结点p(或q)时,递归向上返回说明已经找到了结点p(或q)
- 当遍历到结点q(或p)时,观察其左右子树的返回结果是否说明包含结点p或(q)
- 如果是,则q(或p)就是最终结果
- 否则继续逐层向上返回,直到某个结点的左右子树返回结果都说明了包含p或q
- 这样的算法结果就是最近公共祖先,因为是左右子树同一次返回包含p或q就确定了结果
class Solution {
boolean find = false;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null)
return null;
TreeNode left = lowestCommonAncestor(root.left,p,q);
if(find)
return left;
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(find)
return right;
if((left == p || root == p) && (right == q || root == q) || (root == q || left == q) && (root == p || right == p))
{
find = true;
return root;
}
if(root == p || left == p || right == p)
return p;
if(root == q || left == q || right == q)
return q;
return null;
}
}