Given an N-ary tree root and a list of K nodes, the task is to find the number of common ancestors of the given K nodes in the tree.
Example:
Input: root = 3
/ \
2 1
/ \ / | \
9 7 8 6 3
K = {7, 2, 9}
Output: 2
Explanation: The common ancestors of the nodes 7, 9 and 2 are 2 and 3Input: root = 2
\
1
\
0—4
/ | \
9 3 8
K = {9, 8, 3, 4, 0}
Output: 3
Approach: The given problem can be solved by using the post-order traversal. The idea is to find the lowest common ancestor of the K nodes then increment the count of ancestors for every node above it till the root is reached. Below steps can be followed to solve the problem:
- Add all the list nodes into a set
- Apply post-order traversal on the tree:
- Find the lowest common ancestor then start incrementing the value of the number of nodes at every recursive call
- Return the answer calculated
// C++ implementation for the above approach #include<bits/stdc++.h> using namespace std;
class Node {
public :
vector<Node*> children;
int val;
Node( int val)
{
this ->val = val;
}
}; // Function to find LCA and // count number of ancestors vector<Node*> CAcount(Node* root, set<Node*> st) { // If the current node
// is a desired node
if (st.count(root)) {
vector<Node*> res(2, NULL);
res[0] = root;
res[1] = new Node(1);
return res;
}
// If leaf node then return null
if (root->children.size() == 0) {
vector<Node*> res(2, NULL);
return res;
}
// To count number of desired nodes
// in the children branches
int childCount = 0;
// Initialize a node to return
vector<Node*> ans(2, NULL);
// Iterate through all children
for ( auto child: root->children){
vector<Node*> res = CAcount(child, st);
// Increment child count if
// desired node is found
if (res[0] != NULL)
childCount++;
// If first desired node is found
if (childCount == 1 && ans[0] == NULL) {
ans = res;
}
else if (childCount > 1) {
ans[0] = root;
ans[1] = new Node(1);
return ans;
}
}
// If LCA found below then increment
// number of common ancestors
if (ans[0] != NULL)
ans[1]->val++;
// Return the answer
return ans;
} // Function to find the number // of common ancestors in a tree int numberOfAncestors(Node* root, vector<Node*> nodes)
{ // Initialize a set
set<Node*> st;
// Iterate the list of nodes
// and add them in a set
for ( auto curr: nodes){
st.insert(curr);
}
// Find LCA and return
// number of ancestors
return CAcount(root, st)[1]->val;
} // Driver code int main()
{ // Initialize the tree
Node* zero = new Node(0);
Node* one = new Node(1);
Node* two = new Node(2);
Node* three = new Node(3);
Node* four = new Node(4);
Node* five = new Node(5);
Node* six = new Node(6);
Node* seven = new Node(7);
zero->children.push_back(one);
zero->children.push_back(two);
zero->children.push_back(three);
one->children.push_back(four);
one->children.push_back(five);
five->children.push_back(six);
five->children.push_back(seven);
// List of nodes whose
// ancestors are to be found
vector<Node*> nodes;
nodes.push_back(four);
nodes.push_back(six);
nodes.push_back(seven);
// Call the function
// and print the result
cout << numberOfAncestors(zero, nodes) << endl;
return 0;
} // The code is contributed by Nidhi goel. |
// Java implementation for the above approach import java.io.*;
import java.util.*;
class GFG {
static class Node {
List<Node> children;
int val;
// constructor
public Node( int val)
{
children = new ArrayList<>();
this .val = val;
}
}
// Function to find the number
// of common ancestors in a tree
public static int numberOfAncestors(
Node root,
List<Node> nodes)
{
// Initialize a set
Set<Node> set = new HashSet<>();
// Iterate the list of nodes
// and add them in a set
for (Node curr : nodes) {
set.add(curr);
}
// Find LCA and return
// number of ancestors
return CAcount(root, set)[ 1 ].val;
}
// Function to find LCA and
// count number of ancestors
public static Node[] CAcount(
Node root, Set<Node> set)
{
// If the current node
// is a desired node
if (set.contains(root)) {
Node[] res = new Node[ 2 ];
res[ 0 ] = root;
res[ 1 ] = new Node( 1 );
return res;
}
// If leaf node then return null
if (root.children.size() == 0 ) {
return new Node[ 2 ];
}
// To count number of desired nodes
// in the children branches
int childCount = 0 ;
// Initialize a node to return
Node[] ans = new Node[ 2 ];
// Iterate through all children
for (Node child : root.children) {
Node[] res = CAcount(child, set);
// Increment child count if
// desired node is found
if (res[ 0 ] != null )
childCount++;
// If first desired node is found
if (childCount == 1
&& ans[ 0 ] == null ) {
ans = res;
}
else if (childCount > 1 ) {
ans[ 0 ] = root;
ans[ 1 ] = new Node( 1 );
return ans;
}
}
// If LCA found below then increment
// number of common ancestors
if (ans[ 0 ] != null )
ans[ 1 ].val++;
// Return the answer
return ans;
}
// Driver code
public static void main(String[] args)
{
// Initialize the tree
Node zero = new Node( 0 );
Node one = new Node( 1 );
Node two = new Node( 2 );
Node three = new Node( 3 );
Node four = new Node( 4 );
Node five = new Node( 5 );
Node six = new Node( 6 );
Node seven = new Node( 7 );
zero.children.add(one);
zero.children.add(two);
zero.children.add(three);
one.children.add(four);
one.children.add(five);
five.children.add(six);
five.children.add(seven);
// List of nodes whose
// ancestors are to be found
List<Node> nodes = new ArrayList<>();
nodes.add(four);
nodes.add(six);
nodes.add(seven);
// Call the function
// and print the result
System.out.println(
numberOfAncestors(zero, nodes));
}
} |
# Python3 implementation for the above approach class Node:
def __init__( self , val):
self .children = []
self .val = val
# Function to find the number # of common ancestors in a tree def number_of_ancestors(root, nodes):
set_nodes = set (nodes)
# Find LCA and return
# number of ancestors
return CAcount(root, set_nodes)[ 1 ].val
# Function to find LCA and # count number of ancestors def CAcount(root, set_nodes):
if root in set_nodes:
res = [root, Node( 1 )]
return res
if not root.children:
return [ None , None ]
# To count number of desired nodes
# in the children branches
child_count = 0
ans = [ None , None ]
for child in root.children:
res = CAcount(child, set_nodes)
# Increment child count if
# desired node is found
if res[ 0 ] is not None :
child_count + = 1
if child_count = = 1 and ans[ 0 ] is None :
ans = res
elif child_count > 1 :
ans = [root, Node( 1 )]
return ans
# If LCA found below then increment
# number of common ancestors
if ans[ 0 ] is not None :
ans[ 1 ].val + = 1
return ans
# Initialize the tree zero = Node( 0 )
one = Node( 1 )
two = Node( 2 )
three = Node( 3 )
four = Node( 4 )
five = Node( 5 )
six = Node( 6 )
seven = Node( 7 )
zero.children.append(one) zero.children.append(two) zero.children.append(three) one.children.append(four) one.children.append(five) five.children.append(six) five.children.append(seven) nodes = [four, six, seven]
print (number_of_ancestors(zero, nodes))
# This code is contributed by Potta Lokesh |
// C# implementation for the above approach using System;
using System.Collections.Generic;
public class GFG {
class Node {
public List<Node> children;
public int val;
// constructor
public Node( int val)
{
children = new List<Node>();
this .val = val;
}
}
// Function to find the number
// of common ancestors in a tree
static int numberOfAncestors(
Node root,
List<Node> nodes)
{
// Initialize a set
HashSet<Node> set = new HashSet<Node>();
// Iterate the list of nodes
// and add them in a set
foreach (Node curr in nodes) {
set .Add(curr);
}
// Find LCA and return
// number of ancestors
return CAcount(root, set )[1].val;
}
// Function to find LCA and
// count number of ancestors
static Node[] CAcount(
Node root, HashSet<Node> set )
{
// If the current node
// is a desired node
if ( set .Contains(root)) {
Node[] res = new Node[2];
res[0] = root;
res[1] = new Node(1);
return res;
}
// If leaf node then return null
if (root.children.Count == 0) {
return new Node[2];
}
// To count number of desired nodes
// in the children branches
int childCount = 0;
// Initialize a node to return
Node[] ans = new Node[2];
// Iterate through all children
foreach (Node child in root.children) {
Node[] res = CAcount(child, set );
// Increment child count if
// desired node is found
if (res[0] != null )
childCount++;
// If first desired node is found
if (childCount == 1
&& ans[0] == null ) {
ans = res;
}
else if (childCount > 1) {
ans[0] = root;
ans[1] = new Node(1);
return ans;
}
}
// If LCA found below then increment
// number of common ancestors
if (ans[0] != null )
ans[1].val++;
// Return the answer
return ans;
}
// Driver code
public static void Main(String[] args)
{
// Initialize the tree
Node zero = new Node(0);
Node one = new Node(1);
Node two = new Node(2);
Node three = new Node(3);
Node four = new Node(4);
Node five = new Node(5);
Node six = new Node(6);
Node seven = new Node(7);
zero.children.Add(one);
zero.children.Add(two);
zero.children.Add(three);
one.children.Add(four);
one.children.Add(five);
five.children.Add(six);
five.children.Add(seven);
// List of nodes whose
// ancestors are to be found
List<Node> nodes = new List<Node>();
nodes.Add(four);
nodes.Add(six);
nodes.Add(seven);
// Call the function
// and print the result
Console.WriteLine(
numberOfAncestors(zero, nodes));
}
} // This code is contributed by shikhasingrajput |
<script> // Javascript implementation for the above approach class Node { // constructor
constructor(val) {
this .children = new Array();
this .val = val;
}
} // Function to find the number // of common ancestors in a tree function numberOfAncestors(root, nodes) {
// Initialize a set
let set = new Set();
// Iterate the list of nodes
// and add them in a set
for (curr of nodes) {
set.add(curr);
}
// Find LCA and return
// number of ancestors
return CAcount(root, set)[1].val;
} // Function to find LCA and // count number of ancestors function CAcount(root, set) {
// If the current node
// is a desired node
if (set.has(root)) {
let res = new Node(2);
res[0] = root;
res[1] = new Node(1);
return res;
}
// If leaf node then return null
if (root.children.length == 0) {
return new Node(2);
}
// To count number of desired nodes
// in the children branches
let childCount = 0;
// Initialize a node to return
let ans = new Node(2);
// Iterate through all children
for (child of root.children) {
let res = CAcount(child, set);
// Increment child count if
// desired node is found
if (res[0] != null )
childCount++;
// If first desired node is found
if (childCount == 1
&& ans[0] == null ) {
ans = res;
}
else if (childCount > 1) {
ans[0] = root;
ans[1] = new Node(1);
return ans;
}
}
// If LCA found below then increment
// number of common ancestors
if (ans[0] != null )
ans[1].val++;
// Return the answer
return ans;
} // Driver code // Initialize the tree let zero = new Node(0);
let one = new Node(1);
let two = new Node(2);
let three = new Node(3);
let four = new Node(4);
let five = new Node(5);
let six = new Node(6);
let seven = new Node(7);
zero.children.push(one); zero.children.push(two); zero.children.push(three); one.children.push(four); one.children.push(five); five.children.push(six); five.children.push(seven); // List of nodes whose // ancestors are to be found let nodes = new Array();
nodes.push(four); nodes.push(six); nodes.push(seven); // Call the function // and print the result document.write(numberOfAncestors(zero, nodes)); // This code is contributed by saurabh_jaiswal. </script> |
2
Time Complexity: O(N), where N is the number of nodes in the tree
Auxiliary Space: O(H), H is the height of the tree