236. Lowest Common Ancestor of a Binary Tree

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

CC150 4.7

Solution 1 

946ms   2.91%

public class Solution {
     public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
	        if(root == null || root == p || root == q){
	            return root;
	        }
	        boolean p_left = cover(root.left, p);
	        boolean q_left = cover(root.left, q);
	        
	        if(p_left != q_left){
	            return root;
	        }
	        TreeNode child = p_left? root.left : root.right;
	        return lowestCommonAncestor(child, p, q);
	    }
	    public static boolean cover(TreeNode root, TreeNode p){
	        if(root == null){
	            return false;
	        }
	        if(root == p){
	            return true;
	        }
	        return cover(root.left, p)||cover(root.right, p);
	    }
}


Solution 2 From bottom to top, only needs one time traverse of the tree 

13ms 27.8%

The code below offers an initial solution, but it has a bug.

The problem with this code occurs in the case where a node is not contained in the tree.

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
       if(root == null){
           return null;
       }
       if(root == p && root == q){
           return root;
       }
       if(root == p || root == q){
           return root;
       }
       TreeNode x = lowestCommonAncestor(root.left, p, q);
       if(x != null && x != p && x != q){
           return x;
       }
       
       TreeNode y = lowestCommonAncestor(root.right, p, q);
       if(y != null && y != p && y != q){
           return y;
       }
       
       if(x != null && y != null){
           return root;
       }else{
           return x == null ? y : x;
       }
    }
}


Solution3  

13ms 27.8%

• Case 1: p is a child of q (or, q is a child of p)
• Case 2: p is in the tree and q is not (or, q is in the tree and p is not)
In either of these cases, commonAncestor will return p. In the first case, this is the
correct return value, but in the second case, the return value should be null.
We somehow need to distinguish between these two cases, and this is what the code
below does. This code solves the problem by returning two values: the node itself and a
flag indicating whether this node is actually the common ancestor


public static TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
		Result r = lowestAncestorHelper(root, p, q);
		if (r.isAncestor) {
			return r.node;
		}
		return null;
	}
public static Result lowestAncestorHelper(TreeNode root, TreeNode p, TreeNode q) {
		if (root == null) {
			return new Result(null, false);
		}
		if (root == p && root == q) {
			return new Result(root, true);
		}
		Result rx = lowestAncestorHelper(root.left, p, q);
		if (rx.isAncestor) {
			return rx;
		}
		Result ry = lowestAncestorHelper(root.right, p, q);
		if (ry.isAncestor) {
			return ry;
		}

		if (rx.node != null && ry.node != null) {
			return new Result(root, true);
		} else if (root == p || root == q) {
                /* If we're currently at p or q, and we also found one of
                 * those nodes in a subtree, then this is truly an ancestor
                 * and the flag should be true. */
			boolean isAncestor = rx.node != null || ry.node != null ? true : false;
			return new Result(root, isAncestor);
		} else {
			return new Result(rx.node == null ? ry.node : rx.node, false);
		}
	}

class Result {
	TreeNode node;
	boolean isAncestor;

	public Result(TreeNode n, boolean isAnc) {
		this.node = n;
		this.isAncestor = isAnc;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值