码迷,mamicode.com
首页 > 其他好文 > 详细

公共祖先--binary tree

时间:2015-05-04 13:31:09      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:

找binary tree中两个node第一个公共祖先。注意不一定是BST

想法:p,q都在左子树,就branch left。如果都在right,就branch right。如果不在same side,就返回first common ancestor
所以主要是在left subtree和right subtree中找两个node
 
Solution1 : from cc150
由于covers函数被调用2n nodes(n for left side and n nodes for right side).之后如果在同一边,会继续递归search,还需要check covers,调用2n / 2次,然后 2n/4次。。。
time: O(2n) + O(2n/2) + O(2n / 4) + ... = O(N)
技术分享
 1 public static TreeNode commonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
 2     if (!covers(root, p) || !covers(root, q)) { // Error check - one node is not in tree
 3         return null;
 4     }
 5     return helper(root, p, q);
 6 }
 7 private static TreeNode helper(TreeNode root, TreeNode p, TreeNode q){
 8     if(root == null) return null;
 9     
10     boolean is_p_on_left = covers(root.left, p);
11     boolean is_q_on_left = covers(root.left, q);
12     
13     if(is_p_on_left != is_q_on_left){
14         //nodes are on different side
15         return root;
16     }
17     TreeNode child_side = is_p_on_left ? root.left : root.right;
18     
19     //search in subtree
20     return helper(child_side, p, q);
21 
22 
23 }
24 //check whether p is a descendent of root
25 private static boolean covers(TreeNode root, TreeNode p){
26     if(root == null) return false;
27     
28     if(root == p) return true;
29     
30     return covers(root.left, p) || covers(root.right, p);
31 }
View Code

 类似解法 http://xixiaogualu.blogspot.com/2013/09/lowest-common-ancestor-of-binary-tree.html

top - bottom自顶向下:

技术分享
    public static TreeNode LCA1(TreeNode root,TreeNode n1,TreeNode n2){
        if(exist(root.left,n1) && (exist(root.left,n2))){
            //find in left subtree
            return LCA1(root.left, n1, n2);
        }
        
        if(exist(root.right,n1)&&(exist(root.right,n2))){
            return LCA1(root.right, n1, n2);
        }
        
        return root;
    }
    //find in subtree from root
    public static boolean exist(TreeNode root, TreeNode n){
        if(root == n) return true;
        if(root == null) return false;
        return exist(root.left,n)||exist(root.right,n);
    }
View Code

 

Solution2:改进上面解法 from cc150

Bottom-up ,利用commonAncestor的返回值减少向下search次数,递归调用。

返回值可能的几种情况为:

commonAncestor(TreeNode root, TreeNode p, TreNode q)
  return p, if root‘s subtree includes p (and not q)
  return q, if root‘s subtree includes q( and not p)
  return null, if neighter p nor q in root‘s subtree
  else return common ancestor of p and q
 
技术分享
 1 public static TreeNode LCA(TreeNode root, TreeNode p, TreeNode q){
 2         if(root == null) return null;
 3         if(root == p || root == q){
 4             
 5             return root;
 6         }
 7         
 8         //are child of root
 9         if(p == root.left && q == root.right || p == root.right && q == root.left){
10             return root;
11         }
12         
13         //search in left and right subtree
14         TreeNode left = LCA(root.left, p, q);
15         TreeNode right = LCA(root.right, p, q);
16         
17         if(left != null && right != null){
18             //one is in left subtree and the other is in right
19             return root; 
20         }
21         if(left != null){
22             return left;
23         }
24         if(right != null){
25             return right;
26         }
27         return null;
28 }
View Code

 

拓展: 如果可能p或者q为不在tree里的node,上面bottom up的方法就会产生问题

想法是如果利用这个返回值来区分两种情况:
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)
both cases would return p. but case 2 actually is not ancestor, should be null.
 
借助辅助类
用boolean isAncestor标记case2
 
class Result{
	public TreeNode node;
	public boolean isAncestor;
	public Result(TreeNode n, boolean isAnc){
		node = n;
		isAncestor = isAnc;
	}
}

 

public static TreeNode commonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
	Result res = helper(root, p, q);
	
	if(res.isAncestor){
		return res.node;
	}
	return null;
}

  

技术分享
 1 private static Result helper(TreeNode root, TreeNode p, TreeNode q){
 2     if(root == null){
 3         return new Result(null, false);
 4     }
 5     if(root == p && root == q){
 6         return new Result(root, true);
 7     }
 8     
 9     Result left  = helper(root.left, p, q);
10     if(left.isAncestor){
11         return left;
12     }
13     Result right = helper(root.right, p,q);
14     if(right.isAncestor){
15         return right;
16     }
17     //find common ancestor
18     if(left.node != null && right.node != null){
19         return new Result(root, true);
20     }else if(root == p || root == q){
21         /* If we’re currently at p or q, and we also found one of those
22         nodes in a subtree, then this is truly an ancestor and the
23         flag should be true. */
24         boolean isAncestor = left.node != null || right.node != null; 
25         return new Result(root, isAncestor);
26     }else{
27         //
28         return new Result(left.node != null ? left.node : right.node, false);
29     }
30 }
View Code

 

 

with link to parent
这样只需要trace p and q‘s parents up until intersect. 因为p,q可能不同level,例如q在p子树中。所以要用hashtable来记录已经trace的node。
 或者先move到同一个level,然后同时move up两个指针,判断是否相同,返回第一个相同时的node
 

公共祖先--binary tree

标签:

原文地址:http://www.cnblogs.com/xiaomaoliu/p/4475187.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!