LeetCode – Lowest Common Ancestor of a Binary Tree (Java)

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;
    }
}

13 thoughts on “LeetCode – Lowest Common Ancestor of a Binary Tree (Java)”

  1. 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 ?

  2. 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;
    }

  3. 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));
    }

  4. 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;

    }
    }

  5. Good catch.. Alternatively, we could have:

    numTotal += (root == p ? 1 : 0) + (root == q ? 1 : 0);

  6. 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.

  7. 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);
    }

  8. 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

Leave a Comment