vlambda博客
学习文章列表

二叉树练习题3-最近公共祖先

问题描述:

给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。

最近公共祖先是两个节点的公共的祖先节点且具有最大深度。



样例

对于下面这棵二叉树

            4
/ \
3 7
/ \
5 6

LCA(3, 5) = 4
LCA(5, 6) = 7
LCA(6, 7) = 7





分析:此题可以采用递归的方法做,也可以采用非递归的基于链表和栈的方法来做。


方法一:当遍历到一个root点的时候:


判断root是不是null,如果root为null或者root为所要找的结点,那么直接返回root即可。

如果root的左子树存在p,右子树存在q,则root就肯定是最近祖先

如果p、q都在root的左子树,那么就递归root的左子树,右子树同理

//递归

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {

        // write your code here

        if(root==null || root==A || root==B)    return root;

        TreeNode FindLeft=lowestCommonAncestor(root.left,A,B);

        TreeNode FindRight=lowestCommonAncestor(root.right,A,B);

        if(FindLeft!=null && FindRight!=null){

            return root;

        }else{

            return FindLeft==null?FindRight:FindLeft;

        }

    }

方法二:非递归,基于链表


//非递归,基于链表

    public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode A, TreeNode B) {

        if(root==null || root==A || root==B)    return root;

        ArrayList<TreeNode>  l1=new ArrayList<>();

        ArrayList<TreeNode>  l2=new ArrayList<>();

        FindPath(root,A,l1);

        FindPath(root,B,l2);

        TreeNode result=root;

        for(int i=0;i<l1.size() && i<l2.size();i++){

            if(l1.get(i)==l2.get(i)){

                result=l1.get(i);

            }else{

                break;

            }

        }

        return result;

    }

 

    private boolean FindPath(TreeNode root, TreeNode target, ArrayList<TreeNode> arr){

        if(root==null)  return false;

        arr.add(root);

        if(root==target)  return true;

        if(FindPath(root.left,target,arr) || FindPath(root.right,target,arr))

            return true;

        //没找到,把之前添加到链表中的结点删除

        arr.remove(arr.size()-1);

        return false;

    }

方法三:非递归,基于栈

//非递归,用栈

    public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode A, TreeNode B) {

        if(root==null || root==A || root==B)    return root;

        Stack<TreeNode> s1=new Stack<>();

        Stack<TreeNode> s2=new Stack<>();

        TreeNode result=root;

        if(FindPath1(root,A,s1) && FindPath1(root,B,s2)){

            while(!s1.isEmpty()){

                TreeNode node=s1.pop();

                if(s2.contains(node)){

                    result=node;

                }

            }

        }

        return result;

    }

 

    private boolean FindPath1(TreeNode root,TreeNode target,Stack<TreeNode> stack){

        if(root==null) return false;

        if(root==target){

            stack.push(root);

            return true;

        }

        if(FindPath1(root.left,target,stack) || FindPath1(root.right,target,stack)){

            stack.push(root);

            return true;

        }

        return false;

    }