Open In App

LCA in BST - Lowest Common Ancestor in Binary Search Tree

Last Updated : 11 Feb, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given two nodes n1 and n2 of a Binary Search Tree, find the Lowest Common Ancestor (LCA). You may assume that both values exist in the tree. 

The Lowest Common Ancestor between two nodes n1 and n2 is defined as the lowest node that has both n1 and n2 as descendants (where we allow a node to be a descendant of itself). In other words, the LCA of n1 and n2 is the shared ancestor of n1 and n2 that is located farthest from the root [i.e., closest to n1 and n2].

Examples: 

Input Tree: 

BST_LCA_

Input: LCA of 10 and 14
Output:  12
Explanation: 12 is the closest node to both 10 and 14, which is also an ancestor of both the nodes.

Input: LCA of 8 and 14
Output:  8
Explanation: 8 is the closest node to both 8 and 14, which is also an ancestor of both the nodes.

LCA of Normal Binary Tree Methods - O(n) Time

We can use all the methods discussed in Lowest Common Ancestor in a Binary Tree. The methods discussed there give us the best possible time complexity as O(n) where n is the number of nodes in BST. We can do better if we use BST properties.

Using BST Properties (Recursive Approach) - O(h) Time and O(h) Space

In a Binary search tree, while traversing the tree from top to bottom the first node which lies in between the two numbers n1 and n2 is the LCA of the nodes, i.e. the first node n with the lowest depth which lies in between n1 and n2 (n1 <= n <= n2, assumingn1 < n2). 

So just recursively traverse the BST , if node's value is greater than both n1 and n2 then our LCA lies in the left side of the node, if it is smaller than both n1 and n2, then LCA lies on the right side. Otherwise, the root is LCA (assuming that both n1 and n2 are present in BST).

C++
//Driver Code Starts
// C++ program to find LCA of given node in BST
// Using Properties of BST and Recursion

#include <iostream>
using namespace std;

class Node {
  public:
    int data;
    Node* left;
    Node* right;
    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};
//Driver Code Ends


// Function to find LCA of nodes n1 and n2, assuming
// both are present in the BST
Node* LCA(Node* root, Node* n1, Node* n2) {
  	
    if (root == nullptr)
        return nullptr;

    // If both n1 and n2 are smaller than 
    // root, go to left subtree
    if (root->data > n1->data && root->data > n2->data)
        return LCA(root->left, n1, n2);

    // If both n1 and n2 are greater than 
    // root, go to right subtree
    if (root->data < n1->data && root->data < n2->data)
        return LCA(root->right, n1, n2);

    // If nodes n1 and n2 are on the opposite sides, 
    // then root is the LCA
    return root;
}


//Driver Code Starts
int main() {
  	
  	// Representation of input BST:
    //            20
    //           /  \
    //          8    22
    //        /   \     
    //       4    12   
    //           /   \   
    //         10    14  
    Node* root = new Node(20);
    root->left = new Node(8);
    root->right = new Node(22);
    root->left->left = new Node(4);
    root->left->right = new Node(12);
    root->left->right->left = new Node(10);
    root->left->right->right = new Node(14);

    Node* n1 = root->left->left; // Node 4
    Node* n2 = root->left->right->right; // Node 14

    Node* res = LCA(root, n1, n2);
    cout << res->data << endl;

    return 0;
}

//Driver Code Ends
C
//Driver Code Starts
// C program to find LCA of given node in BST
// Using Properties of BST and Recursion

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node* left;
    struct Node* right;
} Node;

// Utility function to create a new node
Node* newNode(int val) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = val;
    node->left = node->right = NULL;
    return node;
}
//Driver Code Ends


// Function to find LCA of nodes n1 and n2, assuming
// both are present in the BST
Node* LCA(Node* root, Node* n1, Node* n2) {
    if (root == NULL)
        return NULL;

    // If both n1 and n2 are smaller than root, 
  	// go to left subtree
    if (root->data > n1->data && root->data > n2->data)
        return LCA(root->left, n1, n2);

    // If both n1 and n2 are greater than root, 
  	// go to right subtree
    if (root->data < n1->data && root->data < n2->data)
        return LCA(root->right, n1, n2);

    // If nodes n1 and n2 are on the opposite sides, 
  	// root is the LCA
    return root;
}


//Driver Code Starts
int main() {
    // Representation of input BST:
    //            20
    //           /  \
    //          8    22
    //        /   \     
    //       4    12   
    //           /   \   
    //         10    14  
    Node* root = newNode(20);
    root->left = newNode(8);
    root->right = newNode(22);
    root->left->left = newNode(4);
    root->left->right = newNode(12);
    root->left->right->left = newNode(10);
    root->left->right->right = newNode(14);

    Node* n1 = root->left->left; // Node 4
    Node* n2 = root->left->right->right; // Node 14
  
    Node* res = LCA(root, n1, n2);
    printf("%d
", res->data);

    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
// Java program to find LCA of given node in BST
// Using Properties of BST and Recursion

class Node {
    int data;
    Node left, right;

    Node(int val) {
        data = val;
        left = right = null;
    }
}

class GfG {
//Driver Code Ends

  
    // Function to find LCA of nodes n1 and n2, assuming
    // both are present in the BST
    static Node LCA(Node root, Node n1, Node n2) {
        if (root == null)
            return null;

        // If both n1 and n2 are smaller than root, 
      	// go to left subtree
        if (root.data > n1.data && root.data > n2.data)
            return LCA(root.left, n1, n2);

        // If both n1 and n2 are greater than root, 
      	// go to right subtree
        if (root.data < n1.data && root.data < n2.data)
            return LCA(root.right, n1, n2);

        // If nodes n1 and n2 are on the opposite sides, 
      	// root is the LCA
        return root;
    }


//Driver Code Starts
    public static void main(String[] args) {
        // Representation of input BST:
        //            20
        //           /  \
        //          8    22
        //        /   \     
        //       4    12   
        //           /   \   
        //         10    14  
        Node root = new Node(20);
        root.left = new Node(8);
        root.right = new Node(22);
        root.left.left = new Node(4);
        root.left.right = new Node(12);
        root.left.right.left = new Node(10);
        root.left.right.right = new Node(14);

        Node n1 = root.left.left; // Node 4
        Node n2 = root.left.right.right; // Node 14
      
        Node res = LCA(root, n1, n2);
        System.out.println(res.data);
    }
}

//Driver Code Ends
Python
#Driver Code Starts
# Python program to find LCA of given node in BST
# Using Properties of BST and Recursion

class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None
#Driver Code Ends


# Function to find LCA of nodes n1 and n2, assuming
# both are present in the BST
def LCA(root, n1, n2):
    if root is None:
        return None

    # If both n1 and n2 are smaller than root, 
    # go to left subtree
    if root.data > n1.data and root.data > n2.data:
        return LCA(root.left, n1, n2)

    # If both n1 and n2 are greater than root, 
    # go to right subtree
    if root.data < n1.data and root.data < n2.data:
        return LCA(root.right, n1, n2)

    # If nodes n1 and n2 are on the opposite sides, 
    # root is the LCA
    return root


#Driver Code Starts
if __name__ == "__main__":
    # Representation of input BST:
    #            20
    #           /  \
    #          8    22
    #        /   \     
    #       4    12   
    #           /   \   
    #         10    14  
    root = Node(20)
    root.left = Node(8)
    root.right = Node(22)
    root.left.left = Node(4)
    root.left.right = Node(12)
    root.left.right.left = Node(10)
    root.left.right.right = Node(14)

    n1 = root.left.left  # Node 4
    n2 = root.left.right.right  # Node 14
    
    res = LCA(root, n1, n2)
    print(res.data)

#Driver Code Ends
C#
//Driver Code Starts
// C# program to find LCA of given node in BST
// Using Properties of BST and Recursion

using System;

class Node {
    public int data;
    public Node left, right;

    public Node(int val) {
        data = val;
        left = right = null;
    }
}

class GfG {
//Driver Code Ends

  
    // Function to find LCA of nodes n1 and n2, assuming
    // both are present in the BST
    static Node LCA(Node root, Node n1, Node n2) {
        if (root == null)
            return null;

        // If both n1 and n2 are smaller than root,
      	// go to left subtree
        if (root.data > n1.data && root.data > n2.data)
            return LCA(root.left, n1, n2);

        // If both n1 and n2 are greater than root, 
      	// go to right subtree
        if (root.data < n1.data && root.data < n2.data)
            return LCA(root.right, n1, n2);

        // If nodes n1 and n2 are on the opposite sides, 
      	// root is the LCA
        return root;
    }


//Driver Code Starts
    static void Main(string[] args) {
        // Representation of input BST:
        //            20
        //           /  \
        //          8    22
        //        /   \     
        //       4    12   
        //           /   \   
        //         10    14  
        Node root = new Node(20);
        root.left = new Node(8);
        root.right = new Node(22);
        root.left.left = new Node(4);
        root.left.right = new Node(12);
        root.left.right.left = new Node(10);
        root.left.right.right = new Node(14);

        Node n1 = root.left.left; // Node 4
        Node n2 = root.left.right.right; // Node 14
      
        Node res = LCA(root, n1, n2);
        Console.WriteLine(res.data);
    }
}

//Driver Code Ends
JavaScript
//Driver Code Starts
// JavaScript program to find LCA of given node in BST
// Using Properties of BST and Recursion

class Node {
    constructor(val) {
        this.data = val;
        this.left = null;
        this.right = null;
    }
}
//Driver Code Ends


// Function to find LCA of nodes n1 and n2, assuming
// both are present in the BST
function LCA(root, n1, n2) {
    if (root === null)
        return null;

    // If both n1 and n2 are smaller than root, go to left subtree
    if (root.data > n1.data && root.data > n2.data)
        return LCA(root.left, n1, n2);

    // If both n1 and n2 are greater than root, go to right subtree
    if (root.data < n1.data && root.data < n2.data)
        return LCA(root.right, n1, n2);

    // If nodes n1 and n2 are on the opposite sides, root is the LCA
    return root;
}


//Driver Code Starts
// Driver Code
// Representation of input BST:
//            20
//           /  \
//          8    22
//        /   \     
//       4    12   
//           /   \   
//         10    14  
const root = new Node(20);
root.left = new Node(8);
root.right = new Node(22);
root.left.left = new Node(4);
root.left.right = new Node(12);
root.left.right.left = new Node(10);
root.left.right.right = new Node(14);

const n1 = root.left.left; // Node 4
const n2 = root.left.right.right; // Node 14

const res = LCA(root, n1, n2);
console.log(res.data);

//Driver Code Ends

Output
8

Using BST Properties (Iterative Method) - O(h) Time and O(1) Space

The auxiliary space in the above method can be optimized by eliminating recursion. Below is the iterative implementation of this approach.

C++
// C++ program to find LCA of given node in BST
// Using Properties of BST and Iteration

#include <iostream>
using namespace std;

class Node {
  public:
    int data;
    Node* left;
    Node* right;
    Node(int val) {
        data = val;
        left = right = nullptr;
    }
};

// Function to find LCA of n1 and n2, assuming 
// that both nodes n1 and n2 are present in BST 
Node* LCA(Node* root, Node* n1, Node* n2) {

    while (root != nullptr) {
      
        // If both n1 and n2 are smaller than root,
        // then LCA lies in left
        if (root->data > n1->data && root->data > n2->data)
            root = root->left;

        // If both n1 and n2 are greater than root,
        // then LCA lies in right
        else if (root->data < n1->data && root->data < n2->data)
            root = root->right;
        
        // Else Ancestor is found
        else
            break;
    }

    return root;
}

int main() {
  	
  	// Representation of input BST:
    //            20
    //           /  \
    //          8    22
    //        /   \     
    //       4    12   
    //           /   \   
    //         10    14  
    Node* root = new Node(20);
    root->left = new Node(8);
    root->right = new Node(22);
    root->left->left = new Node(4);
    root->left->right = new Node(12);
    root->left->right->left = new Node(10);
    root->left->right->right = new Node(14);

    Node* n1 = root->left->left; // Node 4
    Node* n2 = root->left->right->right; // Node 14

    Node* res = LCA(root, n1, n2);
    cout << res->data << endl;

    return 0;
}
C
// C program to find LCA of given node in BST
// Using Properties of BST and Iteration

#include <stdio.h>
#include <stdlib.h>

// Definition of Node structure
typedef struct Node {
    int data;
    struct Node* left;
    struct Node* right;
} Node;

// Function to create a new node
Node* createNode(int val) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = val;
    newNode->left = newNode->right = NULL;
    return newNode;
}

// Function to find LCA of n1 and n2, assuming 
// that both nodes n1 and n2 are present in BST 
Node* LCA(Node* root, Node* n1, Node* n2) {
    while (root != NULL) {
        // If both n1 and n2 are smaller than root,
        // then LCA lies in left
        if (root->data > n1->data && root->data > n2->data)
            root = root->left;

        // If both n1 and n2 are greater than root,
        // then LCA lies in right
        else if (root->data < n1->data && root->data < n2->data)
            root = root->right;

        // Else Ancestor is found
        else
            break;
    }
    return root;
}

int main() {
    // Representation of input BST:
    //            20
    //           /  \
    //          8    22
    //        /   \     
    //       4    12   
    //           /   \   
    //         10    14  
    Node* root = createNode(20);
    root->left = createNode(8);
    root->right = createNode(22);
    root->left->left = createNode(4);
    root->left->right = createNode(12);
    root->left->right->left = createNode(10);
    root->left->right->right = createNode(14);

    Node* n1 = root->left->left; // Node 4
    Node* n2 = root->left->right->right; // Node 14

    Node* res = LCA(root, n1, n2);
    printf("%d\n", res->data);

    return 0;
}
Java
// Java program to find LCA of given node in BST
// Using Properties of BST and Iteration

class Node {
    int data;
    Node left, right;

    Node(int val) {
        data = val;
        left = right = null;
    }
}

class GfG {

    // Function to find LCA of n1 and n2, assuming
    // that both nodes n1 and n2 are present in BST
    static Node LCA(Node root, Node n1, Node n2) {
      
        while (root != null) {
          
            // If both n1 and n2 are smaller than root,
            // then LCA lies in left
            if (root.data > n1.data && root.data > n2.data)
                root = root.left;

            // If both n1 and n2 are greater than root,
            // then LCA lies in right
            else if (root.data < n1.data && root.data < n2.data)
                root = root.right;

            // Else Ancestor is found
            else
                break;
        }
      
        return root;
    }

    public static void main(String[] args) {
        // Representation of input BST:
        //            20
        //           /  \
        //          8    22
        //        /   \
        //       4    12
        //           /   \
        //         10    14
        Node root = new Node(20);
        root.left = new Node(8);
        root.right = new Node(22);
        root.left.left = new Node(4);
        root.left.right = new Node(12);
        root.left.right.left = new Node(10);
        root.left.right.right = new Node(14);

        Node n1 = root.left.left; // Node 4
        Node n2 = root.left.right.right; // Node 14

        Node res = LCA(root, n1, n2);
        System.out.println(res.data);
    }
}
Python
# C++ program to find LCA of given node in BST
# Using Properties of BST and Iteration

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

# Function to find LCA of n1 and n2, assuming 
# that both nodes n1 and n2 are present in BST
def LCA(root, n1, n2):
  
    while root:
      
        # If both n1 and n2 are smaller than root,
        # then LCA lies in left
        if root.data > n1.data and root.data > n2.data:
            root = root.left
            
        # If both n1 and n2 are greater than root,
        # then LCA lies in right
        elif root.data < n1.data and root.data < n2.data:
            root = root.right
            
        # Else Ancestor is found
        else:
            break
            
    return root

if __name__ == "__main__":
    # Representation of input BST:
    #            20
    #           /  \
    #          8    22
    #        /   \     
    #       4    12   
    #           /   \   
    #         10    14  
    root = Node(20)
    root.left = Node(8)
    root.right = Node(22)
    root.left.left = Node(4)
    root.left.right = Node(12)
    root.left.right.left = Node(10)
    root.left.right.right = Node(14)

    n1 = root.left.left  # Node 4
    n2 = root.left.right.right  # Node 14

    res = LCA(root, n1, n2)
    print(res.data)
C#
// C# program to find LCA of given node in BST
// Using Properties of BST and Iteration

using System;

class Node {
    public int data;
    public Node left, right;

    public Node(int val) {
        data = val;
        left = right = null;
    }
}

class GfG {

    // Function to find LCA of n1 and n2, assuming 
    // that both nodes n1 and n2 are present in BST
    static Node LCA(Node root, Node n1, Node n2) {
      
        while (root != null) {
          
            // If both n1 and n2 are smaller than root,
            // then LCA lies in left
            if (root.data > n1.data && root.data > n2.data)
                root = root.left;
          	
            // If both n1 and n2 are greater than root,
            // then LCA lies in right
          	
            else if (root.data < n1.data && root.data < n2.data)
                root = root.right;
          	
            // Else Ancestor is found
            else
                break;
        }
      	
        return root;
    }

    static void Main(string[] args) {
        // Representation of input BST:
        //            20
        //           /  \
        //          8    22
        //        /   \     
        //       4    12   
        //           /   \   
        //         10    14  
        Node root = new Node(20);
        root.left = new Node(8);
        root.right = new Node(22);
        root.left.left = new Node(4);
        root.left.right = new Node(12);
        root.left.right.left = new Node(10);
        root.left.right.right = new Node(14);

        Node n1 = root.left.left; // Node 4
        Node n2 = root.left.right.right; // Node 14

        Node res = LCA(root, n1, n2);
        Console.WriteLine(res.data);
    }
}
JavaScript
// JavaScript program to find LCA of given node in BST
// Using Properties of BST and Iteration

class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

// Function to find LCA of n1 and n2, assuming 
// that both nodes n1 and n2 are present in BST
function LCA(root, n1, n2) {

    while (root !== null) {
    
        // If both n1 and n2 are smaller than root,
        // then LCA lies in left
        if (root.data > n1.data && root.data > n2.data) 
            root = root.left;
        
        // If both n1 and n2 are greater than root,
        // then LCA lies in right
        else if (root.data < n1.data && root.data < n2.data) 
            root = root.right;
        
        // Else Ancestor is found
        else 
            break;
    }
    return root;
}

// Representation of input BST:
//            20
//           /  \
//          8    22
//        /   \     
//       4    12   
//           /   \   
//         10    14  
const root = new Node(20);
root.left = new Node(8);
root.right = new Node(22);
root.left.left = new Node(4);
root.left.right = new Node(12);
root.left.right.left = new Node(10);
root.left.right.right = new Node(14);

const n1 = root.left.left; // Node 4
const n2 = root.left.right.right; // Node 14

const res = LCA(root, n1, n2);
console.log(res.data);

Output
8

How to handle cases when key(s) not present?

In a BST, we can search a key in O(h) time. So we can first explicitly search the keys and then do find LCA using the above method and still have time complexity as O(h).

Related Articles:
Lowest Common Ancestor in a Binary Tree, LCA using Parent Pointer, Find LCA in Binary Tree using RMQ
 


Next Article

Similar Reads