Find the first common ancestor of two node in binary tree. Attention is not necessarily BST
Idea: The p,q are all in the left subtree, and they are branch. If it's all right, then branch. If you are not in same side, return to first common ancestor so the main is to find two node subtree subtree in left Solution1:from and right cc150 because the covers function is called 2n Nodes (n for left side and N nodes for right side). Then if on the same side, will continue to recursive search, also need check covers, call 2N/2 times, and then 2N/4 times ... Time:o (2n) + O (2N/2) + O (2N/4) + ... = O (N)
1 Public StaticTreeNode CommonAncestor2 (TreeNode root, TreeNode p, TreeNode q) {2 if(!covers (Root, p) | |!covers (root, Q)) {//Error check-one node isn't in tree3 return NULL;4 }5 returnHelper (root, p, q);6 }7 Private StaticTreeNode Helper (TreeNode root, TreeNode p, TreeNode q) {8 if(Root = =NULL)return NULL;9 Ten BooleanIs_p_on_left =Covers (Root.left, p); One BooleanIs_q_on_left =Covers (Root.left, q); A - if(Is_p_on_left! =is_q_on_left) { - //nodes is on different side the returnRoot; - } -TreeNode child_side = is_p_on_left?Root.left:root.right; - + //Search in subtree - returnHelper (Child_side, p, q); + A at } - //Check whether P is a descendent of root - Private Static BooleanCovers (TreeNode root, TreeNode p) { - if(Root = =NULL)return false; - - if(root = = p)return true; in - returnCovers (Root.left, p) | |Covers (Root.right, p); to}
View Code
Similar solution http://xixiaogualu.blogspot.com/2013/09/lowest-common-ancestor-of-binary-tree.html
Top-bottom from top to bottom:
Public StaticTreeNode LCA1 (TreeNode root,treenode n1,treenode n2) {if(exist (ROOT.LEFT,N1) &&(exist (ROOT.LEFT,N2))) { //find in left subtree returnLCA1 (Root.left, N1, N2); } if(exist (ROOT.RIGHT,N1) &&(exist (ROOT.RIGHT,N2))) { returnLCA1 (Root.right, N1, N2); } returnRoot; } //find in subtree from root Public Static Booleanexist (TreeNode root, TreeNode N) {if(Root = = N)return true; if(Root = =NULL)return false; returnexist (Root.left,n) | |exist (root.right,n); }
View Code
Solution2: Improving the above solution from cc150
bottom-up , using the return value of the commonancestor to reduce the number of search down, recursive invocation.
There are several possible cases where the return value is:
Commonancestor (TreeNode root, TreeNode p, Trenode Q) return p, if root ' s subtree includes P (and not Q) return q, if Roo T ' s subtree includes q (and not p) return null, if Neighter p nor Q in root ' s subtree else return common ancestor of p a nd q
1 Public StaticTreeNode LCA (TreeNode root, TreeNode p, TreeNode q) {2 if(Root = =NULL)return NULL;3 if(root = = P | | root = =q) {4 5 returnRoot;6 }7 8 //is child of root9 if(p = = Root.left && q = = Root.right | | p = = Root.right && Q = =root.left) {Ten returnRoot; One } A - //search in left and right subtree -TreeNode left =LCA (Root.left, p, q); theTreeNode right =LCA (Root.right, p, q); - - if(Left! =NULL&& Right! =NULL){ - //subtree and the other are in right + returnRoot; - } + if(Left! =NULL){ A returnLeft ; at } - if(Right! =NULL){ - returnRight ; - } - return NULL; -}
View Code
Expansion: if P or Q is not node in the tree, the bottom up method will cause problems
The idea is that if you use this return value to differentiate between the two cases: case 1:p was a child of Q (or, Q was a child of P) case 2:p was in the tree and Q was not (or, Q was in T He tree and P is not) both cases would return p.
but case 2 actually was not ancestor, should was null.Use the helper class to tag Case2 with a Boolean isancestor
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.isan cestor) {return res.node;} return null;}
1 Private StaticResult Helper (TreeNode root, TreeNode p, TreeNode q) {2 if(Root = =NULL){3 return NewResult (NULL,false);4 }5 if(Root = = P && root = =q) {6 return NewResult (Root,true);7 }8 9Result left =Helper (Root.left, p, q);Ten if(left.isancestor) { One returnLeft ; A } -Result right =Helper (root.right, p,q); - if(right.isancestor) { the returnRight ; - } - //Find common ancestor - if(Left.node! =NULL&& Right.node! =NULL){ + return NewResult (Root,true); -}Else if(root = = P | | root = =q) { + /*If we ' re currently at p or Q, and we also found one of the those A nodes in a subtree, then this is truly an ancestor and the at flag should be true.*/ - BooleanIsAncestor = left.node! =NULL|| Right.node! =NULL; - return NewResult (root, isancestor); -}Else{ - // - return NewResult (Left.node! =NULL? Left.node:right.node,false); in } -}
View Code
With link to parent this requires only trace p and Q ' s parents up until intersect.
because p,q may be different level, for example Q in the P- subtree。 So use Hashtable to record the already-trace node. or move to the same level, then move up two pointers at the same time to determine if the same, return the first node of the same time
Common ancestor--binary Tree