一文解决二叉树的公共祖先的相关问题
首先明确一个概念:什么是公共祖先?百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
若根据以上的定义,若root是p,q的公共祖先,只可能是以下3种情况:
p和q分别在root的左子树和右子树中
p == root ,p在q的左子树或右子树中
q == root ,q在p的左子树或右子树中
所以可以考虑使用递归,二叉树的问题使用递归的方式基本都可以解决,递归的出口为:
如果root == null || root == p || root == q
则直接返回root,否则接着递归root的左子树和右子树并返回,如果递归的左子树和右子树的结果都为空则仍返回root
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left == null) return right;
if(right == null) return left;
return root;
}
扩展:二叉搜索树的最近公共祖先
作为二叉搜索树的祖先问题就相对简单一点,直接迭代就可以,无需使用递归的方式即可
循环搜索:basecase:当节点为null时跳出;
当p,q都在root的右子树中,直接继续向右子树遍历root = root.right
当p,q都在root的右子树中,直接继续向右子树遍历root = root.right
当p,q在root的两侧时,直接返回root
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null) {
if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
root = root.right; // 遍历至右子节点
else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
root = root.left; // 遍历至左子节点
else break;
}
return root;
}