Least Common Ancestor of any number of nodes in Binary Tree - GeeksforGeeks

01 Nov, 2021
Given a binary tree (not a binary search tree) and any number of Key Nodes, the task is to find the least common ancestor of all the key Nodes. 
Following is the definition of LCA from Wikipedia: 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).
The LCA of any number of nodes in T is the shared common ancestor of the nodes that is located farthest from the root.  
Example: In the figure above: 
LCA of nodes 12, 14, 15 is node 3
LCA of nodes 3, 14, 15 is node 3
LCA of nodes 6, 7, 15 is node 3
LCA of nodes 5, 13, 14, 15 is node 1
LCA of nodes 6, 12 is node 6
Approach: Following is the simple approach for Least Common Ancestor for any number of nodes.  
For every node calculate the matching number of nodes at that node and its sub-tree. If root is also a matching node.
If root is also a matching node.
matchingNodes = matchingNodes in left sub-tree + matchingNodes in right sub-tree + 1  
If root is not a matching node.
matchingNodes = matchingNodes in left sub-tree + matchingNodes in right-subtree  
If matching Nodes count at any node is equal to number of keys then add that node into the Ancestors list.
The First node in the Ancestors List is the Least Common Ancestor of all the given keys.
Below is the implementation of above approach. 
C++
Java
Python3
C#
Javascript
// C++ implementation to find// Ancestors of any number of nodes#include <bits/stdc++.h>using namespace std; // Tree Classclass TreeNode{    public:        int data;        TreeNode *left, *right;                 TreeNode(int value)        {            this->data = value;            this->left = NULL;            this->right = NULL;        }}; int getKeysCount(TreeNode *root, vector<int> &keyNodes,                 int matchingNodes,                 vector<TreeNode *> &ancestors){         // Base Case. When root is Null    if (root == NULL)    {        return 0;    }         // Search for left and right subtree    // for matching child Key Node.    matchingNodes += getKeysCount(root->left, keyNodes,                                  matchingNodes, ancestors) +                     getKeysCount(root->right, keyNodes,                                  matchingNodes, ancestors);         // Condition to check if Root Node    // is also in Key Node    if (find(keyNodes.begin(),             keyNodes.end(), root->data) != keyNodes.end())    {        matchingNodes++;    }         // Condition when matching Nodes is    // equal to the Key Nodes found    if (matchingNodes == keyNodes.size())    {        ancestors.push_back(root);    }         return matchingNodes;} // Function to find Least Common// Ancestors of N number of nodesTreeNode *lcaOfNodes(TreeNode *root,                     vector<int> &keyNodes){         // Create a new list for    // capturing all the ancestors    // of the given nodes    vector<TreeNode *> ancestors;         // Initially there is No Matching Nodes    int matchingNodes = 0;    getKeysCount(root, keyNodes,                 matchingNodes, ancestors);         // First Node in the Ancestors list    // is the Least Common Ancestor of    // Given keyNodes    return ancestors[0];} // Driver Codeint main(){         // Creation of Tree    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);    root->left->left->left = new TreeNode(8);    root->left->left->right = new TreeNode(9);    root->left->right->left = new TreeNode(10);    root->left->right->right = new TreeNode(11);    root->right->left->left = new TreeNode(12);    root->right->left->right = new TreeNode(13);    root->right->right->left = new TreeNode(14);    root->right->right->right = new TreeNode(15);         // Key Nodes for LCA    vector<int> keyNodes;    keyNodes.push_back(12);    keyNodes.push_back(14);    keyNodes.push_back(15);         cout << lcaOfNodes(root, keyNodes)->data         << endl;         return 0;} // This code is contributed by sanjeev2552
// Java implementation to find// Ancestors of any number of nodesimport java.util.ArrayList; // Tree Classclass TreeNode {    int data;    TreeNode left;    TreeNode right;     public TreeNode(int value)    {        this.data = value;        left = right = null;    }} public class LCAofAnyNumberOfNodes {         // Function to find Least Common    // Ancestors of N number of nodes    public static TreeNode lcaOfNodes(        TreeNode root,        ArrayList<Integer> keyNodes)    {        // Create a new list for        // capturing all the ancestors        // of the given nodes        ArrayList<TreeNode> ancestors =                    new ArrayList<TreeNode>();                 // Initially there is No Matching Nodes        int matchingNodes = 0;        getKeysCount(root, keyNodes,                 matchingNodes, ancestors);         // First Node in the Ancestors list        // is the Least Common Ancestor of        // Given keyNodes        return ancestors.get(0);    }     private static int getKeysCount(        TreeNode root, ArrayList<Integer> keyNodes,        int matchingNodes,        ArrayList<TreeNode> ancestors)    {        // Base Case. When root is Null        if (root == null)            return 0;         // Search for left and right subtree        // for matching child Key Node.        matchingNodes += getKeysCount(root.left,                keyNodes, matchingNodes, ancestors)            + getKeysCount(root.right,                keyNodes, matchingNodes, ancestors);                 // Condition to check if Root Node         // is also in Key Node        if (keyNodes.contains(root.data)){            matchingNodes++;        }         // Condition when matching Nodes is        // equal to the Key Nodes found        if (matchingNodes == keyNodes.size())            ancestors.add(root);        return matchingNodes;    }         // Driver Code    public static void main(String[] args)    {                 // Creation of Tree        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);        root.left.left.left =                        new TreeNode(8);        root.left.left.right =                        new TreeNode(9);        root.left.right.left =                        new TreeNode(10);        root.left.right.right =                        new TreeNode(11);        root.right.left.left =                        new TreeNode(12);        root.right.left.right =                        new TreeNode(13);        root.right.right.left =                        new TreeNode(14);        root.right.right.right =                        new TreeNode(15);                 // Key Nodes for LCA        ArrayList<Integer> keyNodes =                new ArrayList<Integer>();        keyNodes.add(12);        keyNodes.add(14);        keyNodes.add(15);        System.out.println(            lcaOfNodes(root, keyNodes).data        );    }}
# Python3 implementation to find# Ancestors of any number of nodes # Tree Classclass TreeNode:    def __init__(self, value):        self.data = value        self.left = None        self.right = None # Create a new list for# capturing all the ancestors# of the given nodesancestors =  []  # Function to find Least Common# Ancestors of N number of nodesdef lcaOfNodes(root, keyNodes):       # Initially there is No Matching Nodes    matchingNodes = 0    getKeysCount(root, keyNodes, matchingNodes)      # First Node in the Ancestors list    # is the Least Common Ancestor of    # Given keyNodes    ancestors[0].data-=1    return ancestors[0]  def getKeysCount(root, keyNodes, matchingNodes):    # Base Case. When root is Null    if root == None:        return 0      # Search for left and right subtree    # for matching child Key Node.    matchingNodes += getKeysCount(root.left, keyNodes, matchingNodes) + getKeysCount(root.right, keyNodes, matchingNodes)           # Condition to check if Root Node    # is also in Key Node    if keyNodes:        matchingNodes+=1      # Condition when matching Nodes is    # equal to the Key Nodes found    if matchingNodes == len(keyNodes):        ancestors.append(root)    return matchingNodes # Creation of Treeroot = TreeNode(1)root.left = TreeNode(2)root.right = TreeNode(3)root.left.left = TreeNode(4)root.left.right = TreeNode(5)root.right.left = TreeNode(6)root.right.right = TreeNode(7)root.left.left.left = TreeNode(8)root.left.left.right = TreeNode(9)root.left.right.left = TreeNode(10)root.left.right.right = TreeNode(11)root.right.left.left = TreeNode(12)root.right.left.right = TreeNode(13)root.right.right.left = TreeNode(14)root.right.right.right = TreeNode(15)   # Key Nodes for LCAkeyNodes = []keyNodes.append(12)keyNodes.append(14)keyNodes.append(15)tmp = lcaOfNodes(root, keyNodes)print(tmp.data) # This code is contributed by suresh07.
// C# implementation to find// Ancestors of any number of nodesusing System;using System.Collections.Generic; // Tree Classclass TreeNode {    public int data;    public TreeNode left;    public TreeNode right;      public TreeNode(int value)    {        this.data = value;        left = right = null;    }}  public class LCAofAnyNumberOfNodes {          // Function to find Least Common    // Ancestors of N number of nodes    static TreeNode lcaOfNodes(        TreeNode root,        List<int> keyNodes)    {        // Create a new list for        // capturing all the ancestors        // of the given nodes        List<TreeNode> ancestors =                    new List<TreeNode>();                  // Initially there is No Matching Nodes        int matchingNodes = 0;        getKeysCount(root, keyNodes,                 matchingNodes, ancestors);          // First Node in the Ancestors list        // is the Least Common Ancestor of        // Given keyNodes        return ancestors[0];    }      private static int getKeysCount(        TreeNode root, List<int> keyNodes,        int matchingNodes,        List<TreeNode> ancestors)    {        // Base Case. When root is Null        if (root == null)            return 0;          // Search for left and right subtree        // for matching child Key Node.        matchingNodes += getKeysCount(root.left,                keyNodes, matchingNodes, ancestors)            + getKeysCount(root.right,                keyNodes, matchingNodes, ancestors);                  // Condition to check if Root Node         // is also in Key Node        if (keyNodes.Contains(root.data)){            matchingNodes++;        }          // Condition when matching Nodes is        // equal to the Key Nodes found        if (matchingNodes == keyNodes.Count)            ancestors.Add(root);        return matchingNodes;    }          // Driver Code    public static void Main(String[] args)    {                  // Creation of Tree        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);        root.left.left.left =                        new TreeNode(8);        root.left.left.right =                        new TreeNode(9);        root.left.right.left =                        new TreeNode(10);        root.left.right.right =                        new TreeNode(11);        root.right.left.left =                        new TreeNode(12);        root.right.left.right =                        new TreeNode(13);        root.right.right.left =                        new TreeNode(14);        root.right.right.right =                        new TreeNode(15);                  // Key Nodes for LCA        List<int> keyNodes = new List<int>();        keyNodes.Add(12);        keyNodes.Add(14);        keyNodes.Add(15);        Console.WriteLine(            lcaOfNodes(root, keyNodes).data        );    }} // This code is contributed by PrinciRaj1992
<script>  // JavaScript implementation to find// Ancestors of any number of nodes // Tree Classclass TreeNode {     constructor(value)    {        this.data = value;        this.left = null;        this.right = null;    }}  // Create a new list for// capturing all the ancestors// of the given nodesvar ancestors =  []; // Function to find Least Common// Ancestors of N number of nodesfunction lcaOfNodes( root, keyNodes){          // Initially there is No Matching Nodes    var matchingNodes = 0;    getKeysCount(root, keyNodes,             matchingNodes);     // First Node in the Ancestors list    // is the Least Common Ancestor of    // Given keyNodes    return ancestors[0];} function getKeysCount( root, keyNodes, matchingNodes){    // Base Case. When root is Null    if (root == null)        return 0;     // Search for left and right subtree    // for matching child Key Node.    matchingNodes += getKeysCount(root.left,            keyNodes, matchingNodes)        + getKeysCount(root.right,            keyNodes, matchingNodes);          // Condition to check if Root Node     // is also in Key Node    if (keyNodes.includes(root.data)){        matchingNodes++;    }     // Condition when matching Nodes is    // equal to the Key Nodes found    if (matchingNodes == keyNodes.length)        ancestors.push(root);    return matchingNodes;}  // Driver Code// Creation of Treevar 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);root.left.left.left =                new TreeNode(8);root.left.left.right =                new TreeNode(9);root.left.right.left =                new TreeNode(10);root.left.right.right =                new TreeNode(11);root.right.left.left =                new TreeNode(12);root.right.left.right =                new TreeNode(13);root.right.right.left =                new TreeNode(14);root.right.right.right =                new TreeNode(15);  // Key Nodes for LCAvar keyNodes = [];keyNodes.push(12);keyNodes.push(14);keyNodes.push(15);var tmp = lcaOfNodes(root, keyNodes);document.write(tmp.data); </script>
3
 
princiraj1992
sanjeev2552
simranarora5sos
noob2000
varshagumber28
suresh07
Binary Tree
LCA
Algorithms
Data Structures
Recursion
Tree
Data Structures
Recursion
Tree
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
DSA Sheet by Love Babbar
How to Start Learning DSA?
Difference between Algorithm, Pseudocode and Program
K means Clustering - Introduction
Types of Complexity Classes | P, NP, CoNP, NP hard and NP complete
Difference between Stack and Queue Data Structures
What is Competitive Programming and How to Prepare for It?
Data Structures | Linked List | Question 5
Data Structures | Tree Traversals | Question 4
FIFO (First-In-First-Out) approach in Programming