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>
Output
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