Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
Java Solution 1
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null) return null; if(root==p || root==q) return root; TreeNode l = lowestCommonAncestor(root.left, p, q); TreeNode r = lowestCommonAncestor(root.right, p, q); if(l!=null&&r!=null){ return root; }else if(l==null&&r==null){ return null; }else{ return l==null?r:l; } } |
To calculate time complexity, we know that f(n)=2*f(n-1)=2*2*f(n-2)=2^(logn), so time=O(n).
Java Solution 2
class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { CounterNode n = helper(root, p, q); return n.node; } public CounterNode helper(TreeNode root, TreeNode p, TreeNode q){ if(root==null){ return new CounterNode(null, 0); } CounterNode left = helper(root.left, p, q); if(left.count==2){ return left; } CounterNode right = helper(root.right, p, q); if(right.count==2){ return right; } int c=left.count+right.count+(root==p?1:0)+(root==q?1:0); return new CounterNode(root, c); } } class CounterNode{ public int count; public TreeNode node; public CounterNode(TreeNode node, int count){ this.count=count; this.node=node; } } |
Solution 2 is the correct one, as the first solution will fail if one of the node is not in the tree, I wonder why is that marked as deprecated ?
I created my solution : LCA of BST
your solution is great, but I think that applies only if is a BST, not for a simple Binary Tree.
http://www.programcreek.com/2014/07/leetcode-lowest-common-ancestor-of-a-binary-search-tree-java/
Here is my recursive version of the solution-
static TreeNode lowestCommAncesterRecu( TreeNode root, int a, int b)
{
if(root != null )
{
if(root.value == a || root.value == b){
return root;
}
if(root.value > a && root.value < b)
{
return root;
}
if(root.value b)
{
return root;
}
if(root.value > a && root.value > b)
{
root = lowestCommAncesterRecu(root.leftNode,a,b);
}
if(root.value < a && root.value < b)
{
root =lowestCommAncesterRecu(root.rightNode,a,b);
}
}
return root;
}
Following code working tested :
public int lca(TreeNode a, int val1, int val2) {
        if(find(a, val1) == -1 || find(a, val2) == -1) return -1;
        TreeNode l = LCA(a,val1,val2);
        return l == null ? -1 : l.val;
}
public TreeNode LCA(TreeNode a, int val1, int val2) {
        if(a == null) return null;
        if(a.val == val1 || a.val == val2) return a;
        TreeNode l1 = LCA(a.left, val1, val2);
        TreeNode l2 = LCA(a.right, val1, val2);
        if(l1 != null && l2 != null) return a;
        if(l1 == null && l2 == null) return null;
        return l1 != null ? l1 : l2;
}
public int find(TreeNode a, int val){
        if(a == null) return -1;
        if(a.val == val) return 1;
        return Math.max(find(a.left, val), find(a.right, val));
}
Solution 1 doesn’t work for the case when one of the nodes in ancestor of the other. Correct Solution should be as follows :
public class Solution {
Boolean flag1,flag2;
public int lca(TreeNode a, int val1, int val2) {
flag1 = flag2 = false;
if(a==null) return -1;
if(a.left == null && a.right == null)
{
return (a.val == val1 && val1==val2) ? a.val : -1;
}
TreeNode temp = find_lca(a,val1,val2);
if(flag1 && flag2) return temp.val;
else return -1;
}
public TreeNode find_lca(TreeNode node,int val1,int val2)
{
TreeNode lca=null;
if(node == null) return null;
if(node.val == val1)
{
this.flag1 = true;
lca = node;
//return node;
}
if(node.val == val2)
{
this.flag2 = true;
lca = node;
// return node;
}
TreeNode l = find_lca(node.left,val1,val2);
TreeNode r = find_lca(node.right,val1,val2);
if((l != null && r!=null) || (lca != null)) return node;
return l!=null ? l:r;
}
}
Here’s another solution (java):
https://gist.github.com/hmny/cbfc98029ae746dbd14a83f96c294ef7
This is a great analysis. I also read an in-depth discussion about this question here http://bit.ly/29kAkXM.
Good catch.. Alternatively, we could have:
numTotal += (root == p ? 1 : 0) + (root == q ? 1 : 0);
Solution 1 doesn’t work in the case of p == q. Should replace
if(root== p || root == q){
numTotal++;
}
with
if (root == p) {
numTotal ++;
}
if (root == q) {
numTotal ++;
}
or add a check at the beginning.
Tried on leetcode online judge, and it didn’t pass.
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return findLCA(root, p.val, q.val);
}
The above code doesn’t seem to work if Btree happens to be BST. Also here is the more simpler one.
public class LcaBinaryTree {
TreeNode findLCA(TreeNode root, int n1, int n2) {
// Base case
if (root == null)
return null;
// If either n1 or n2 matches with root's key, report
// the presence by returning root (Note that if a key is
// ancestor of other, then the ancestor key becomes LCA
if (root.data == n1 || root.data == n2)
return root;
// Look for keys in left and right subtrees
TreeNode left_lca = findLCA(root.left, n1, n2);
TreeNode right_lca = findLCA(root.right, n1, n2);
// If both of the above calls return Non-NULL, then one key
// is present in once subtree and other is present in other,
// So this node is the LCA
if (left_lca != null && right_lca != null)
return root;
// Otherwise check if left subtree or right subtree is LCA
return (left_lca != null) ? left_lca : right_lca;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);
// BTreePrinter.printNode(root);
LcaBinaryTree lca = new LcaBinaryTree();
System.out.println("lca(6 , 7): " + lca.findLCA(root, 6, 7).data);
System.out.println("lca(4 , 5): " + lca.findLCA(root, 4, 5).data);
System.out.println("lca(2 , 3): " + lca.findLCA(root, 2, 3).data);
}
}
Output of the program:
1
/
/
2 3
/ /
4 5 6 7
lca(6 , 7): 3
lca(4 , 5): 2
lca(2 , 3): 1
Could you please explain the code and its complexity? Thanks!