Lowest Common Ancestor in a Binary Tree | Practice | GeeksforGeeks

Given a Binary Tree with all unique values and two nodes value, n1 and n2. The task is to find the lowest common ancestor of the given two nodes. We may assume that either both n1 and n2 are present in the tree or none of them are present. 
Example 1:
Input:
n1 = 2 , n2 = 3  
       1 
      / \ 
     2   3
Output: 1
Explanation:
LCA of 2 and 3 is 1.
Example 2:
Input:
n1 = 3 , n2 = 4
           5    
          /    
         2  
        / \  
       3   4
Output: 2
Explanation:
LCA of 3 and 4 is 2. 
Your Task:
You don't have to read, input, or print anything. Your task is to complete the function lca() that takes nodes, n1, and n2 as parameters and returns the LCA node as output. 
Expected Time Complexity:O(N).
Expected Auxiliary Space:O(Height of Tree).
Constraints:
1 ≤ Number of nodes ≤ 105
1 ≤ Data of a node ≤ 105
+204
rainx7 months ago
LUCID EXPLAINATION
The question is simply asking to find the subtree's root which will contain both n1 and n2, right?! So we do the same,
 
Well, if there is no root, you gotta return null/root. if(root==nullptr) { return root; }  if your root data contains either n1 or n2, you return that root. WHY?? because it will be used in calculation of two different answer A.K.A. left and right side of tree.Now save your Left answer of the left side of tree in a variable, this variable with either have a null or a valid node depending on recursive calls if it finds the required node, Do the same for the Right side make a variable and save the answer.Now, we have two different variables namely left and right. Both contains answer either null or a valid node, now we check three conditionsIf Left answer is not null and right answer is also not null, then the answer is the root itself, since left and right are subtrees of the root and if both are not null it clearly means the values n1 and n2 lies in right as well as left side, For example, Example test case 1 is the perfect example for this caseIf left answer is not null but right answer is null, then it means both n1 and n2 lies on the left side of tree inside the subtree with root as left answer, return left answer. For example, Example test case 2 is the perfect example for this case If right answer is not null but left answer is null, then it means both n1 and n2 lies on the right side of tree inside the subtree with root as right answer, return right answer.
Well, if there is no root, you gotta return null/root. if(root==nullptr) { return root; }  
if your root data contains either n1 or n2, you return that root. WHY?? because it will be used in calculation of two different answer A.K.A. left and right side of tree.
Now save your Left answer of the left side of tree in a variable, this variable with either have a null or a valid node depending on recursive calls if it finds the required node, Do the same for the Right side make a variable and save the answer.
Now, we have two different variables namely left and right. Both contains answer either null or a valid node, now we check three conditions
If Left answer is not null and right answer is also not null, then the answer is the root itself, since left and right are subtrees of the root and if both are not null it clearly means the values n1 and n2 lies in right as well as left side, For example, Example test case 1 is the perfect example for this case
If left answer is not null but right answer is null, then it means both n1 and n2 lies on the left side of tree inside the subtree with root as left answer, return left answer. For example, Example test case 2 is the perfect example for this case
 If right answer is not null but left answer is null, then it means both n1 and n2 lies on the right side of tree inside the subtree with root as right answer, return right answer.
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
                     **SPOLIER ALERT CODE AHEAD**
 
 
 
CODE IMPLEMENTATION
 
Node* lca(Node* root ,int n1 ,int n2 ) {

        if(root==nullptr){
            return root;
        }
        
        if(root->data==n1 || root->data==n2){
            return root;
        }
        
        Node* LEFTSIDE  =lca(root->left,n1,n2);
        Node* RIGHTSIDE =lca(root->right,n1,n2);
        
        if(LEFTSIDE!=nullptr && RIGHTSIDE!=nullptr){
            return root;
        } 
        
        else if(LEFTSIDE!=nullptr){
            return LEFTSIDE;
        }
        
        else{
            return RIGHTSIDE;
        }
        
}
 
Relevant Right? 🤣🤣🤣🤣🤣🤣
 
 
THANKS FOR READING AND DO CARE TO UPVOTE.....😴😴😴
 
edit: thanks for the crazy amount of upvotes,, appreciate it
0
sharmarahul996111 week ago
       if(root==NULL) return NULL;      if(root->data==n1 || root->data ==n2){          return root;      }      Node*l = lca(root->left , n1 ,n2);      Node*r= lca(root->right , n1 ,n2);      if(l!=NULL && r!=NULL){          return root;       }       if(l!=NULL)return l;       if(r!=NULL) return r;
0
harendersingh78962 weeks ago
class Solution
{
    //Function to return the lowest common ancestor in a Binary Tree.
	Node lca(Node root, int n1,int n2)
	{
		// Your code here
		if(root == null || root.data == n1 || root.data == n2)
		{
		    return root;
		}
		
		if(root.data == n1 || root.data == n2)
		{
		    return root;
		}
		
		Node left = lca(root.left, n1, n2);
		Node right = lca(root.right, n1, n2);
		
		if(left == null)
		{
		    return right;
		}
		else if(right == null)
		{
		    return left;
		}
		else
		{
		    return root;
		}
		
	}
}ja
0
saisaran22 weeks ago
finding the path to reach both nodes and finding common division point of both path
class Solution{   public:   bool hasPath(Node *root, vector<Node*>& arr, int x){   if (!root)   {       return false;   }   arr.push_back(root);      if (root->data == x)   {       return true;   }   if (hasPath(root->left, arr, x) ||       hasPath(root->right, arr, x))       return true;   arr.pop_back();   return false;           }   Node* lca(Node* root ,int n1 ,int n2 )   {       vector<Node*>v1;       vector<Node*>v2;       hasPath(root,v1,n1);       hasPath(root,v2,n2);       int n=min(v1.size(),v2.size());       Node* c=root;
       for(int i=0;i<n;i++)       {                      if(v1[i]->data!=v2[i]->data)           {               c=v1[i-1];               break;           }       }       if(v1[n-1]->data==v2[n-1]->data)       {           return v1[n-1];       }       return c;   }};
0
tarunkanade2 weeks ago
0.69/2.06 Java O(n) O(h) with comments
Node lca(Node root, int n1,int n2)
	{
		// Your code here
		if(root == null){
		    return null;
		}
		
		// if current node matches with the given values then this is the ancestor
		if(root.data == n1 || root.data == n2){
		    return root;
		}
		
		// check the same in left and right
		Node left = lca(root.left, n1, n2);
		Node right = lca(root.right, n1, n2);
		
		// if both left and right have some values that means in both subtrees
		// we found one one value and that means the current node is the immediate
		// ancestor of those nodes (you have to think recursively), we processed
		// subtrees so after returning from the above two calls we are at upper level
		if(left != null && right != null){
		    return root;
		}
		
		// if left is not null that means this is the ancestor of either both (when
		// right will return null) or itself (right will return something)
		else if(left != null){
		    return left;
		}
		
		// otherwise return right, it may be null or may not be, but due to recursive
		// chanining we will return correct ans (again you have to think recursively)
		else{
		    return right;
		}
	}
0
shubham211019972 weeks ago
class Solution
{
  boolean path(Node root,int n,ArrayList<Node>arr){
      if(root==null)return false;
      arr.add(root);
      if(root.data==n)return true;
      if(path(root.left,n,arr)==true ||path(root.right,n,arr)==true)
         return true;
      arr.remove(arr.size()-1);
      return false;
  }
Node lca(Node root, int n1,int n2)
{
ArrayList<Node>arr1=new ArrayList<>();
ArrayList<Node>arr2=new ArrayList<>();
   boolean p1=path(root,n1,arr1);
    boolean p2=path(root,n2,arr2);
 if(p1==false ||p2==false)return null;
 int i;
 for( i=0;i<arr1.size()&& i<arr2.size();i++){
     if(arr1.get(i).data!=arr2.get(i).data) break;
 }
    return arr1.get(i-1);  
}
}

0
ashi11100001112 weeks ago
Node* lca(Node* root ,int n1 ,int n2 )   {      //Your code here       if(root==NULL)          return 0;            if(root->data==n1 || root->data==n2)          return root;           Node* left = lca(root->left ,n1, n2);     Node* right = lca(root->right, n1 ,n2);            if(left==NULL)      return right;            if(right==NULL)      return left;            return root;   }
0
2018uee01551 month ago
Python  the most Naive Solution
 
class Solution:
    #Function to return the lowest common ancestor in a Binary Tree.
    def lca(self,root, n1, n2):
        # Code here
        if(root==None):
            return root
        if(root.data==n1 or root.data==n2):
            return root
        left=self.lca(root.left,n1,n2)
        right=self.lca(root.right,n1,n2)
        
        if(left!=None and right!=None):
            return root
        elif(left!=None):
            return left
        else:
            return right
0
rohanmeher1641 month ago
// simple java solution
 
class Solution{   //Function to return the lowest common ancestor in a Binary Tree.Node lca(Node root, int n1,int n2){ if(root== null) return null;  if(root.data==n1 || root.data==n2) return root;  Node l=lca(root.left,n1,n2); Node r=lca(root.right,n1,n2);  if(l!=null && r!=null) return root;  else if(l!=null) return l;  else return r;}}
-1
agrimjain24111 month ago
Efficient C++ Code using pair (Only 1 traversal and O(1) space)
class Solution
{
    public:
    //Function to return the lowest common ancestor in a Binary Tree.
    Node* LCA = new Node(-1);
    Node* lca(Node* root ,int n1 ,int n2 )
    {
       //Your code here
       findLCA(n1,n2,root);
       return LCA;
    }
    
    pair<int,int> findLCA(int x,int y, Node*root)
    {
        if(root==NULL)
        return {0,0};
        // p.first tells if x(n1) exist in subtree
        // p.second tells if y(n2) exist in subtree
        
        pair<int,int>l = findLCA(x,y,root->left);
        pair<int,int>r = findLCA(x,y,root->right);
        
        if((LCA->data ==-1) && ((root->data == x && (l.second+r.second>=1)) 
        ||(root->data == y && (l.first+r.first>=1))
        ||(l.first + r.second == 2)
        ||(r.first + l.second ==2)))
        {
            LCA = root;
            return {1,1};
        }
        
        pair<int,int>p = {0,0};
        
        if(root->data==x ||((l.first + r.first >= 1)))
            p.first = 1;
        
        if(root->data==y ||((l.second + r.second >= 1)))
            p.second = 1;
            
        return p;
    }
};


We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code. On submission, your code is tested against multiple test cases consisting of all possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as the final solution code.
You can view the solutions submitted by other users from the submission tab.