寻找二叉树的最近公共祖先
这道题在面试过程遇到了两次了,感觉是一个高频考点,特此总结一下
解题思路:
祖先定义: 若节点p 在节点root 的左子树或者右子树中,则称root是p的祖先
最近公共祖先的定义: 设节点root 为节点p,q的最近公共祖先,若其左子节点root.left,和右子节点
root.right 都不是p,q的公共祖先在,则称root 是最近的公共祖先
根据以上定义,若root是p,q的最近公共祖先,则只可能为以下情况之一:
1,p和q在root的子树中,且分列root的两侧,即分别为左右子树中。
2, p = root ,且q 在root 的左或右子树中
3,q = root,且 p 在root 的左或者右子树中
考虑通过递归对二叉树进行后续遍历,当遇到节点p 或者q 时返回,从底至顶回溯,当节点p ,q,在节点root两侧时,即为最近公共祖先,则向上返回root
递归解析
1,终止条件:
1,当越过叶子节点,则直接返回Null
2,当root 等于p ,q,则直接返回root
2.递推工作
1,开启递归左子节点,返回值记为left
2, 开启递归右子节点,返回值记为right
3, 返回值
1,当left 和right 同时为空,说明,root 的左/右子树中都不包含p,q. 返回Null
2, 当left 和right 同时不为空,说明,p,q,分别在root的两侧,因此root为最近的公共祖先,返回root
3, 当left 为空,right 不为空: p,q 都不在root 的左子树中,直接返回right,具体可分为两种情况:
-
p,q, 其中一个在root 的右子树中,p 或者q 就是root 的右子树, 此时right 指向 p(假设为p )
-
p,q,两个基点都在root的右子树中,此时的right 指向最近的公共祖先节点
4,当left 不为空,right 为空,直接返回left ,与3 同理
public static TreeNode lowestCommonAncestor (TreeNode root ,TreeNode p,TreeNoe 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 &&right === null ){return null;}
if(left == null ){return right; }
if(right == null ){return left; }
return root;
}
验证:
import java.util.*;
public class TreeExercise1 {
public static void main(String[] args ){
TreeNode p3 = new TreeNode(3);
TreeNode p5 = new TreeNode(5);
TreeNode p1 = new TreeNode(1);
TreeNode p6 = new TreeNode(6);
TreeNode p2 = new TreeNode(2);
TreeNode p0 = new TreeNode(0);
TreeNode p8 = new TreeNode(8);
TreeNode p7 = new TreeNode(7);
TreeNode p4 = new TreeNode(4);
p3.left = p5;
p3.right = p1;
p5.left = p6;
p5.right = p2;
p1.left = p0;
p1.right = p8;
p2.left = p7;
p2.right = p4;
// inorferFix(p3);
TreeNode res = lowestCommonAncestor(p3,p2,p6);
inorderFix(res);
}
public static 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 && right == null ){ return null; }
if(left == null ){return right; }
if(right == null ){return left ; }
return root;
}
private static void inorferFix(TreeNode root ){
if(root==null ){
return;
}
if(root.left != null ){
inorferFix(root.left);
}