Open In App

Lowest Common Ancestor in a Binary Tree using Parent Pointer

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given values of two nodes in a Binary Tree, find the Lowest Common Ancestor (LCA). It may be assumed that both nodes exist in the tree.

BST_LCA

For example, consider the Binary Tree in diagram, LCA of 10 and 14 is 12 and LCA of 8 and 14 is 8.

Let T be a rooted tree. The lowest common ancestor between two nodes n1 and n2 is defined as the lowest node in T that has both n1 and n2 as descendants (where we allow a node to be a descendant of itself). Source : Wikipedia.

   

We have discussed different approaches to find LCA in set 1. Finding LCA becomes easy when parent pointer is given as we can easily find all ancestors of a node using parent pointer. Below are steps to find LCA.

  1. Create an empty hash table.
  2. Insert n1 and all of its ancestors in hash table.
  3. Check if n2 or any of its ancestors exist in hash table, if yes return the first existing ancestor.

Below is the implementation of above steps. 

C++14




// C++ program to find lowest common ancestor using parent pointer
#include <bits/stdc++.h>
using namespace std;
 
// A Tree Node
struct Node
{
    Node *left, *right, *parent;
    int key;
};
 
// A utility function to create a new BST node
Node *newNode(int item)
{
    Node *temp = new Node;
    temp->key = item;
    temp->parent = temp->left = temp->right = NULL;
    return temp;
}
 
/* A utility function to insert a new node with
   given key in Binary Search Tree */
Node *insert(Node *node, int key)
{
    /* If the tree is empty, return a new node */
    if (node == NULL) return newNode(key);
 
    /* Otherwise, recur down the tree */
    if (key < node->key)
    {
        node->left  = insert(node->left, key);
        node->left->parent = node;
    }
    else if (key > node->key)
    {
        node->right = insert(node->right, key);
        node->right->parent = node;
    }
 
    /* return the (unchanged) node pointer */
    return node;
}
 
// To find LCA of nodes n1 and n2 in Binary Tree
Node *LCA(Node *n1, Node *n2)
{
   // Create a map to store ancestors of n1
   map <Node *, bool> ancestors;
 
   // Insert n1 and all its ancestors in map
   while (n1 != NULL)
   {
       ancestors[n1] = true;
       n1 = n1->parent;
   }
 
   // Check if n2 or any of its ancestors is in
   // map.
   while (n2 != NULL)
   {
       if (ancestors.find(n2) != ancestors.end())
           return n2;
       n2 = n2->parent;
   }
 
   return NULL;
}
 
// Driver method to test above functions
int main(void)
{
    Node * root = NULL;
 
    root = insert(root, 20);
    root = insert(root, 8);
    root = insert(root, 22);
    root = insert(root, 4);
    root = insert(root, 12);
    root = insert(root, 10);
    root = insert(root, 14);
 
    Node *n1 = root->left->right->left;
    Node *n2 = root->left;
    Node *lca = LCA(n1, n2);
 
    printf("LCA of %d and %d is %d \n", n1->key, n2->key, lca->key);
 
    return 0;
}


Java




import java.util.HashMap;
import java.util.Map;
 
// Java program to find lowest common ancestor using parent pointer
// A tree node
class Node
{
    int key;
    Node left, right, parent;
 
    Node(int key)
    {
        this.key = key;
        left = right = parent = null;
    }
}
 
class BinaryTree
{
    Node root, n1, n2, lca;
 
    /* A utility function to insert a new node with
       given key in Binary Search Tree */
    Node insert(Node node, int key)
    {
        /* If the tree is empty, return a new node */
        if (node == null)
            return new Node(key);
 
        /* Otherwise, recur down the tree */
        if (key < node.key)
        {
            node.left = insert(node.left, key);
            node.left.parent = node;
        }
        else if (key > node.key)
        {
            node.right = insert(node.right, key);
            node.right.parent = node;
        }
 
        /* return the (unchanged) node pointer */
        return node;
    }
 
    // To find LCA of nodes n1 and n2 in Binary Tree
    Node LCA(Node n1, Node n2)
    {
        // Create a map to store ancestors of n1
        Map<Node, Boolean> ancestors = new HashMap<Node, Boolean>();
 
        // Insert n1 and all its ancestors in map
        while (n1 != null)
        {
            ancestors.put(n1, Boolean.TRUE);
            n1 = n1.parent;
        }
 
        // Check if n2 or any of its ancestors is in
        // map.
        while (n2 != null)
        {
            if (ancestors.containsKey(n2) != ancestors.isEmpty())
                return n2;
            n2 = n2.parent;
        }
 
        return null;
    }
 
    // Driver method to test above functions
    public static void main(String[] args)
    {
        BinaryTree tree = new BinaryTree();
        tree.root = tree.insert(tree.root, 20);
        tree.root = tree.insert(tree.root, 8);
        tree.root = tree.insert(tree.root, 22);
        tree.root = tree.insert(tree.root, 4);
        tree.root = tree.insert(tree.root, 12);
        tree.root = tree.insert(tree.root, 10);
        tree.root = tree.insert(tree.root, 14);
 
        tree.n1 = tree.root.left.right.left;
        tree.n2 = tree.root.left;
        tree.lca = tree.LCA(tree.n1, tree.n2);
 
        System.out.println("LCA of " + tree.n1.key + " and " + tree.n2.key
                + " is " + tree.lca.key);
    }
}
 
// This code has been contributed by Mayank Jaiswal(mayank_24)


Python3




# Python program to find lowest common ancestor using parent pointer
global root
root = None
 
# A Tree Node
class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.parent = None
 
# A utility function to insert a new node with given key in Binary Search Tree
def insert(root, key):
    # If the tree is empty, return a new node
    if root == None:
        return Node(key)
 
    # Otherwise, recur down the tree
    if key < root.key:
        root.left = insert(root.left, key)
        root.left.parent = root
    elif key > root.key:
        root.right = insert(root.right, key)
        root.right.parent = root
    # return the (unchanged) node pointer
    return root
 
# To find LCA of nodes n1 and n2 in Binary Tree
def LCA(n1, n2):
    # Create a map to store ancestors of n1
    ancestors = {}
 
    # Insert n1 and all its ancestors in map
    while n1 != None:
        ancestors[n1] = True
        n1 = n1.parent
 
    # Check if n2 or any of its ancestors is in map.
    while n2 != None:
        if n2 in ancestors:
            return n2
 
        n2 = n2.parent
 
    return None
 
# Driver method to test above functions
if __name__ == '__main__':
 
    root = insert(root, 20)
    root = insert(root, 8)
    root = insert(root, 22)
    root = insert(root, 4)
    root = insert(root, 12)
    root = insert(root, 10)
    root = insert(root, 14)
 
    n1 = root.left.right.left
    n2 = root.left
    lca = LCA(n1, n2)
 
    print("LCA of", n1.key, "and", n2.key, "is", lca.key)
 
# This code is contributed by Tapesh(tapeshdua420)


C#




// C# program to find lowest common ancestor using parent pointer
// A tree node
using System;
using System.Collections;
using System.Collections.Generic;
 
public class Node
{
    public int key;
    public Node left, right, parent;
 
    public Node(int key)
    {
        this.key = key;
        left = right = parent = null;
    }
}
 
class BinaryTree
{
    Node root, n1, n2, lca;
 
    /* A utility function to insert a new node with
    given key in Binary Search Tree */
    Node insert(Node node, int key)
    {
        /* If the tree is empty, return a new node */
        if (node == null)
            return new Node(key);
 
        /* Otherwise, recur down the tree */
        if (key < node.key)
        {
            node.left = insert(node.left, key);
            node.left.parent = node;
        }
        else if (key > node.key)
        {
            node.right = insert(node.right, key);
            node.right.parent = node;
        }
 
        /* return the (unchanged) node pointer */
        return node;
    }
 
    // To find LCA of nodes n1 and n2 in Binary Tree
    Node LCA(Node n1, Node n2)
    {
        // Create a map to store ancestors of n1
        Dictionary<Node, Boolean> ancestors = new Dictionary<Node, Boolean>();
 
        // Insert n1 and all its ancestors in map
        while (n1 != null)
        {
            ancestors.Add(n1,true);
            n1 = n1.parent;
        }
 
        // Check if n2 or any of its ancestors is in
        // map.
        while (n2 != null)
        {
            if (ancestors.ContainsKey(n2))
                return n2;
            n2 = n2.parent;
        }
 
        return null;
    }
 
    // Driver code
    public static void Main(String []args)
    {
        BinaryTree tree = new BinaryTree();
        tree.root = tree.insert(tree.root, 20);
        tree.root = tree.insert(tree.root, 8);
        tree.root = tree.insert(tree.root, 22);
        tree.root = tree.insert(tree.root, 4);
        tree.root = tree.insert(tree.root, 12);
        tree.root = tree.insert(tree.root, 10);
        tree.root = tree.insert(tree.root, 14);
 
        tree.n1 = tree.root.left.right.left;
        tree.n2 = tree.root.left;
        tree.lca = tree.LCA(tree.n1, tree.n2);
 
        Console.WriteLine("LCA of " + tree.n1.key + " and " + tree.n2.key
                + " is " + tree.lca.key);
    }
}
 
// This code is contributed by Arnab Kundu


Javascript




// Javascript code for above approach
 
// A Tree Node
class Node {
    constructor(left, right, parent, key) {
        this.left = left;
        this.right = right;
        this.parent = parent;
        this.key = key;
    }
}
 
// A utility function to create a new BST node
function newNode(item) {
    let temp = new Node();
    temp.key = item;
    temp.parent = temp.left = temp.right = null;
    return temp;
}
 
/* A utility function to insert a new node with
given key in Binary Search Tree */
function insert(node, key) {
    /* If the tree is empty, return a new node */
    if (node == null) return newNode(key);
 
    /* Otherwise, recur down the tree */
    if (key < node.key) {
        node.left = insert(node.left, key);
        node.left.parent = node;
    } else if (key > node.key) {
        node.right = insert(node.right, key);
        node.right.parent = node;
    }
 
    /* return the (unchanged) node pointer */
    return node;
}
 
// To find LCA of nodes n1 and n2 in Binary Tree
function LCA(n1, n2) {
    // Create a map to store ancestors of n1
    let ancestors = new Map();
 
    // Insert n1 and all its ancestors in map
    while (n1 != null) {
        ancestors.set(n1, true);
        n1 = n1.parent;
    }
 
    // Check if n2 or any of its ancestors is in
    // map.
    while (n2 != null) {
        if (ancestors.has(n2)) return n2;
        n2 = n2.parent;
    }
 
    return null;
}
 
// Driver method to test above functions
let root = null;
 
root = insert(root, 20);
root = insert(root, 8);
root = insert(root, 22);
root = insert(root, 4);
root = insert(root, 12);
root = insert(root, 10);
root = insert(root, 14);
 
let n1 = root.left.right.left;
let n2 = root.left;
let lca = LCA(n1, n2);
 
console.log(`LCA of ${n1.key} and ${n2.key} is ${lca.key}`);
 
// This code is contributed by adityamaharshi21


Output:

LCA of 10 and 8 is 8 

Note : The above implementation uses insert of Binary Search Tree to create a Binary Tree, but the function LCA is for any Binary Tree (not necessarily a Binary Search Tree). Time Complexity : O(h) where h is height of Binary Tree if we use hash table to implement the solution (Note that the above solution uses map which takes O(Log h) time to insert and find). So the time complexity of above implementation is O(h Log h). Auxiliary Space : O(h)   A O(h) time and O(1) Extra Space Solution: The above solution requires extra space because we need to use a hash table to store visited ancestors. We can solve the problem in O(1) extra space using following fact : If both nodes are at same level and if we traverse up using parent pointers of both nodes, the first common node in the path to root is lca. The idea is to find depths of given nodes and move up the deeper node pointer by the difference between depths. Once both nodes reach same level, traverse them up and return the first common node. Thanks to Mysterious Mind for suggesting this approach. 

C++




// C++ program to find lowest common ancestor using parent pointer
#include <bits/stdc++.h>
using namespace std;
 
// A Tree Node
struct Node
{
    Node *left, *right, *parent;
    int key;
};
 
// A utility function to create a new BST node
Node *newNode(int item)
{
    Node *temp = new Node;
    temp->key = item;
    temp->parent = temp->left = temp->right = NULL;
    return temp;
}
 
/* A utility function to insert a new node with
given key in Binary Search Tree */
Node *insert(Node *node, int key)
{
    /* If the tree is empty, return a new node */
    if (node == NULL) return newNode(key);
 
    /* Otherwise, recur down the tree */
    if (key < node->key)
    {
        node->left = insert(node->left, key);
        node->left->parent = node;
    }
    else if (key > node->key)
    {
        node->right = insert(node->right, key);
        node->right->parent = node;
    }
 
    /* return the (unchanged) node pointer */
    return node;
}
 
// A utility function to find depth of a node
// (distance of it from root)
int depth(Node *node)
{
    int d = -1;
    while (node)
    {
        ++d;
        node = node->parent;
    }
    return d;
}
 
// To find LCA of nodes n1 and n2 in Binary Tree
Node *LCA(Node *n1, Node *n2)
{
    // Find depths of two nodes and differences
    int d1 = depth(n1), d2 = depth(n2);
    int diff = d1 - d2;
 
    // If n2 is deeper, swap n1 and n2
    if (diff < 0)
    {
        Node * temp = n1;
        n1 = n2;
        n2 = temp;
        diff = -diff;
    }
 
    // Move n1 up until it reaches the same level as n2
    while (diff--)
        n1 = n1->parent;
 
    // Now n1 and n2 are at same levels
    while (n1 && n2)
    {
        if (n1 == n2)
            return n1;
        n1 = n1->parent;
        n2 = n2->parent;
    }
 
    return NULL;
}
 
// Driver method to test above functions
int main(void)
{
    Node * root = NULL;
 
    root = insert(root, 20);
    root = insert(root, 8);
    root = insert(root, 22);
    root = insert(root, 4);
    root = insert(root, 12);
    root = insert(root, 10);
    root = insert(root, 14);
 
    Node *n1 = root->left->right->left;
    Node *n2 = root->right;
 
    Node *lca = LCA(n1, n2);
    printf("LCA of %d and %d is %d \n", n1->key, n2->key, lca->key);
 
    return 0;
}


Java




import java.util.HashMap;
import java.util.Map;
 
// Java program to find lowest common ancestor using parent pointer
 
// A tree node
class Node
{
    int key;
    Node left, right, parent;
 
    Node(int key)
    {
        this.key = key;
        left = right = parent = null;
    }
}
 
class BinaryTree
{
    Node root, n1, n2, lca;
 
    /* A utility function to insert a new node with
       given key in Binary Search Tree */
    Node insert(Node node, int key)
    {
        /* If the tree is empty, return a new node */
        if (node == null)
            return new Node(key);
 
        /* Otherwise, recur down the tree */
        if (key < node.key)
        {
            node.left = insert(node.left, key);
            node.left.parent = node;
        }
        else if (key > node.key)
        {
            node.right = insert(node.right, key);
            node.right.parent = node;
        }
 
        /* return the (unchanged) node pointer */
        return node;
    }
 
    // A utility function to find depth of a node
    // (distance of it from root)
    int depth(Node node)
    {
        int d = -1;
        while (node != null)
        {
            ++d;
            node = node.parent;
        }
        return d;
    }
 
    // To find LCA of nodes n1 and n2 in Binary Tree
    Node LCA(Node n1, Node n2)
    {
        // Find depths of two nodes and differences
        int d1 = depth(n1), d2 = depth(n2);
        int diff = d1 - d2;
 
        // If n2 is deeper, swap n1 and n2
        if (diff < 0)
        {
            Node temp = n1;
            n1 = n2;
            n2 = temp;
            diff = -diff;
        }
 
        // Move n1 up until it reaches the same level as n2
        while (diff-- != 0)
            n1 = n1.parent;
 
        // Now n1 and n2 are at same levels
        while (n1 != null && n2 != null)
        {
            if (n1 == n2)
                return n1;
            n1 = n1.parent;
            n2 = n2.parent;
        }
 
        return null;
    }
 
    // Driver method to test above functions
    public static void main(String[] args)
    {
        BinaryTree tree = new BinaryTree();
        tree.root = tree.insert(tree.root, 20);
        tree.root = tree.insert(tree.root, 8);
        tree.root = tree.insert(tree.root, 22);
        tree.root = tree.insert(tree.root, 4);
        tree.root = tree.insert(tree.root, 12);
        tree.root = tree.insert(tree.root, 10);
        tree.root = tree.insert(tree.root, 14);
 
        tree.n1 = tree.root.left.right.left;
        tree.n2 = tree.root.right;
        tree.lca = tree.LCA(tree.n1, tree.n2);
 
        System.out.println("LCA of " + tree.n1.key + " and " + tree.n2.key
                + " is " + tree.lca.key);
    }
}
 
// This code has been contributed by Mayank Jaiswal(mayank_24)


Python3




# Python program to find lowest common ancestor using parent pointer
 
# A tree node
class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.parent = None
 
 
class BinaryTree:
    def __init__(self):
        self.root = None
        self.n1 = None
        self.n2 = None
        self.lca = None
 
    # A utility function to insert a new node with
    #   given key in Binary Search Tree
    def insert(self, node, key):
        # If the tree is empty, return a new node
        if node == None:
            return Node(key)
 
        # Otherwise, recur down the tree
        if key < node.key:
            node.left = self.insert(node.left, key)
            node.left.parent = node
 
        elif key > node.key:
            node.right = self.insert(node.right, key)
            node.right.parent = node
 
        # return the (unchanged) node pointer
        return node
 
    # A utility function to find depth of a node (distance of it from root)
    def depth(self, node):
        d = -1
        while(node != None):
            d += 1
            node = node.parent
        return d
 
    # To find LCA of nodes n1 and n2 in Binary Tree
    def LCA(self, n1, n2):
        # Find depths of two nodes and differences
        d1 = self.depth(n1)
        d2 = self.depth(n2)
        diff = d1-d2
 
        # If n2 is deeper, swap n1 and n2
        if diff < 0:
            temp = n1
            n1 = n2
            n2 = temp
            diff = -diff
 
        # Move n1 up until it reaches the same level as n2
        while diff != 0:
            n1 = n1.parent
            diff -= 1
 
        # Now n1 and n2 are at same levels
        while n1 != None and n2 != None:
            if (n1 == n2):
                return n1
            n1 = n1.parent
            n2 = n2.parent
 
        return None
 
 
# Driver method to test above functions
if __name__ == '__main__':
    tree = BinaryTree()
    tree.root = tree.insert(tree.root, 20)
    tree.root = tree.insert(tree.root, 8)
    tree.root = tree.insert(tree.root, 22)
    tree.root = tree.insert(tree.root, 4)
    tree.root = tree.insert(tree.root, 12)
    tree.root = tree.insert(tree.root, 10)
    tree.root = tree.insert(tree .root, 14)
 
    tree.n1 = tree.root.left.right.left
    tree.n2 = tree.root.right
    tree.lca = tree.LCA(tree.n1, tree.n2)
 
    print("LCA of " + str(tree.n1.key) + " and " +
          str(tree.n2.key) + " is " + str(tree .lca .key))
 
# This code is contributed by Tapesh(tapesh1308)


C#




// C# program to find lowest common
// ancestor using parent pointer
using System;
 
// A tree node
public class Node
{
    public int key;
    public Node left, right, parent;
 
    public Node(int key)
    {
        this.key = key;
        left = right = parent = null;
    }
}
 
class GFG
{
public Node root, n1, n2, lca;
 
/* A utility function to insert a new
 node with given key in Binary Search Tree */
public virtual Node insert(Node node, int key)
{
    /* If the tree is empty, return
       a new node */
    if (node == null)
    {
        return new Node(key);
    }
 
    /* Otherwise, recur down the tree */
    if (key < node.key)
    {
        node.left = insert(node.left, key);
        node.left.parent = node;
    }
    else if (key > node.key)
    {
        node.right = insert(node.right, key);
        node.right.parent = node;
    }
 
    /* return the (unchanged) node pointer */
    return node;
}
 
// A utility function to find depth of a
// node (distance of it from root)
public virtual int depth(Node node)
{
    int d = -1;
    while (node != null)
    {
        ++d;
        node = node.parent;
    }
    return d;
}
 
// To find LCA of nodes n1 and n2
// in Binary Tree
public virtual Node LCA(Node n1, Node n2)
{
    // Find depths of two nodes
    // and differences
    int d1 = depth(n1), d2 = depth(n2);
    int diff = d1 - d2;
 
    // If n2 is deeper, swap n1 and n2
    if (diff < 0)
    {
        Node temp = n1;
        n1 = n2;
        n2 = temp;
        diff = -diff;
    }
 
    // Move n1 up until it reaches
    // the same level as n2
    while (diff-- != 0)
    {
        n1 = n1.parent;
    }
 
    // Now n1 and n2 are at same levels
    while (n1 != null && n2 != null)
    {
        if (n1 == n2)
        {
            return n1;
        }
        n1 = n1.parent;
        n2 = n2.parent;
    }
 
    return null;
}
 
// Driver Code
public static void Main(string[] args)
{
    GFG tree = new GFG();
    tree.root = tree.insert(tree.root, 20);
    tree.root = tree.insert(tree.root, 8);
    tree.root = tree.insert(tree.root, 22);
    tree.root = tree.insert(tree.root, 4);
    tree.root = tree.insert(tree.root, 12);
    tree.root = tree.insert(tree.root, 10);
    tree.root = tree.insert(tree.root, 14);
 
    tree.n1 = tree.root.left.right.left;
    tree.n2 = tree.root.right;
    tree.lca = tree.LCA(tree.n1, tree.n2);
 
    Console.WriteLine("LCA of " + tree.n1.key +
                      " and " + tree.n2.key +
                      " is " + tree.lca.key);
}
}
 
// This code is contributed by Shrikant13


Javascript




// Javascript code for above approach
  
// A Tree Node
class Node {
    constructor(left, right, parent, key) {
        this.left = left;
        this.right = right;
        this.parent = parent;
        this.key = key;
    }
}
 
// A utility function to create a new BST node
function newNode(item) {
    let temp = new Node();
    temp.key = item;
    temp.parent = temp.left = temp.right = null;
    return temp;
}
 
// A utility function to insert a new node with
// given key in Binary Search Tree
function insert(node, key){
    // If the tree is empty, return a new node
    if (node == null) return newNode(key);
  
    // Otherwise, recur down the tree
    if (key < node.key){
        node.left = insert(node.left, key);
        node.left.parent = node;
    }
    else if (key > node.key){
        node.right = insert(node.right, key);
        node.right.parent = node;
    }
  
    // return the (unchanged) node pointer
    return node;
}
 
// A utility function to find depth of a node
// (distance of it from root)
function depth(node){
    let d = -1;
    while(node){
        ++d;
        node = node.parent;
    }
    return d;
}
 
// To find LCA of nodes n1 and n2 in Binary Tree
function LCA(n1, n2){
    // Find depths of two nodes and differences
    let d1 = depth(n1), d2 = depth(n2);
    let diff = d1 - d2;
  
    // If n2 is deeper, swap n1 and n2
    if (diff < 0){
        let temp = n1;
        n1 = n2;
        n2 = temp;
        diff = -diff;
    }
  
    // Move n1 up until it reaches the same level as n2
    while (diff--)
        n1 = n1.parent;
  
    // Now n1 and n2 are at same levels
    while (n1 && n2){
        if (n1 == n2)
            return n1;
        n1 = n1.parent;
        n2 = n2.parent;
    }
  
    return null;
}
 
// Driver method to test above functions
let root = null;
  
root = insert(root, 20);
root = insert(root, 8);
root = insert(root, 22);
root = insert(root, 4);
root = insert(root, 12);
root = insert(root, 10);
root = insert(root, 14);
  
let n1 = root.left.right.left;
let n2 = root.right;
let lca = LCA(n1, n2);
 
console.log(`LCA of ${n1.key} and ${n2.key} is ${lca.key}`);
// this code is contributed by Yash Agarwal(yashagarwal2852002)


Output : 

LCA of 10 and 22 is 20 

Time Complexity : O(h)

Space Complexity : O(1)

You may like to see below articles as well : Lowest Common Ancestor in a Binary Tree | Set 1 Lowest Common Ancestor in a Binary Search Tree. Find LCA in Binary Tree using RMQ



Last Updated : 14 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads