Given an N-ary tree as a list of nodes Node[] tree. Each node has a unique value, the task is to find the root of the tree.
Examples:
Input: 1
/ | \
2 3 4
\
5Output: Root value is 1
Input: 5
/ | \
3 6 7
/ \ / \
9 2 1 8Output: Root value is 5
Naive approach: To solve the problem follow the below idea:
The basic way to find the root of an N-ary tree, we can iterate over each node and will check if it appears as a child node in any other node this way if we find a node that doesn’t appear as a child in any other node can be said or considered as the root of the tree.
Time Complexity: O(N*N), where N is the number of nodes
Auxiliary Space: O(N) where N is the number of nodes
Efficient approach: To solve the problem follow the below idea:
In order to find the root of an N-ary tree we can utilize the properties of a tree structure, as we know in a generic tree the root node does not appear as a child so we will iterate over each node and keep track of their parents and the node without a parent is the root of the tree.
Illustrations:
Let’s consider the below example to understand the above approach easily
Tree : 1
/ | \
2 3 4
|
5Steps of illustrations:
- Begin with an empty dictionary to hold each node’s parents.
- Iterate through the tree nodes.
- Iterate over the children of each node
- For each child node, add an item to the parent dictionary with the key being the child node and the value being the parent node.
- We will have a dictionary that maps each child’s node to its parent node after iterating over all nodes and their children.
- Iterate through the tree, looking for nodes that have children in other nodes.
- If a node does not appear as a child in any other node, it is called the tree’s root.
- In the given example, the node 1 doesn’t appear as a child in any other node so it can be said that node 1 is the root node.
Below is the implementation of the above approach in Python:
#include <iostream> #include <vector> #include <unordered_map> class Node {
public :
int value;
std::vector<Node*> children;
Node( int value) : value(value) {}
}; Node* findRoot(std::vector<Node*>& tree) { std::unordered_map<Node*, Node*> parents;
// Iterate over each node and its children
for (Node* node : tree) {
for (Node* child : node->children) {
parents[child] = node;
}
}
// Find the root node by checking for a node without a parent
for (Node* node : tree) {
if (parents.find(node) == parents.end()) {
return node;
}
}
// No root found
return nullptr;
} int main() {
// Create the nodes for the given example tree
Node* node1 = new Node(5);
Node* node2 = new Node(3);
Node* node3 = new Node(6);
Node* node4 = new Node(7);
Node* node5 = new Node(9);
Node* node6 = new Node(2);
Node* node7 = new Node(1);
Node* node8 = new Node(8);
// Define the relationships between the nodes
node1->children = { node2, node3, node4 };
node2->children = { node5, node6 };
node4->children = { node7, node8 };
// Create the vector of nodes representing the tree
std::vector<Node*> tree = { node1, node2, node3, node4, node5,
node6, node7, node8 };
// Find the root of the tree
Node* root = findRoot(tree);
// Print the value of the root node
if (root) {
std::cout << "Root value: " << root->value << std::endl;
} else {
std::cout << "No root found." << std::endl;
}
// Clean up the dynamically allocated nodes
for (Node* node : tree) {
delete node;
}
return 0;
} |
// Java program of the above approach import java.util.*;
class Node {
int value;
List<Node> children;
Node( int value)
{
this .value = value;
this .children = new ArrayList<>();
}
} public class GFG {
static Node findRoot(List<Node> tree)
{
Map<Node, Node> parents = new HashMap<>();
// Iterate over each node and its children
for (Node node : tree) {
for (Node child : node.children) {
parents.put(child, node);
}
}
// Find the root node by checking for a node without
// a parent
for (Node node : tree) {
if (!parents.containsKey(node)) {
return node;
}
}
// No root found
return null ;
}
public static void main(String[] args)
{
// Create the nodes for the given example tree
Node node1 = new Node( 5 );
Node node2 = new Node( 3 );
Node node3 = new Node( 6 );
Node node4 = new Node( 7 );
Node node5 = new Node( 9 );
Node node6 = new Node( 2 );
Node node7 = new Node( 1 );
Node node8 = new Node( 8 );
// Define the relationships between the nodes
node1.children.add(node2);
node1.children.add(node3);
node1.children.add(node4);
node2.children.add(node5);
node2.children.add(node6);
node4.children.add(node7);
node4.children.add(node8);
// Create the list of nodes representing the tree
List<Node> tree = new ArrayList<>();
tree.add(node1);
tree.add(node2);
tree.add(node3);
tree.add(node4);
tree.add(node5);
tree.add(node6);
tree.add(node7);
tree.add(node8);
// Find the root of the tree
Node root = findRoot(tree);
// Print the value of the root node
if (root != null ) {
System.out.println( "Root value: " + root.value);
}
else {
System.out.println( "No root found." );
}
}
} // This code is contributed by Susobhan Akhuli |
class Node:
def __init__( self , value):
self .value = value
self .children = []
def find_root(tree):
parents = {}
# Iterate over each node
# and its children
for node in tree:
for child in node.children:
parents[child] = node
# Find the root node by checking
# for a node without a parent
for node in tree:
if node not in parents:
return node
# No root found return None
# Create the nodes for the # given example tree node1 = Node( 5 )
node2 = Node( 3 )
node3 = Node( 6 )
node4 = Node( 7 )
node5 = Node( 9 )
node6 = Node( 2 )
node7 = Node( 1 )
node8 = Node( 8 )
# Define the relationships # between the nodes node1.children = [node2, node3, node4]
node2.children = [node5, node6]
node4.children = [node7, node8]
# Create the list of nodes # representing the tree tree = [node1, node2, node3,
node4, node5, node6, node7, node8]
# Find the root of the tree root = find_root(tree)
# Print the value of # the root node if root:
print ("Root value:", root.value)
else :
print ("No root found.")
|
// C# program of the above approach using System;
using System.Collections.Generic;
public class Node {
public int Value;
public List<Node> Children;
public Node( int value)
{
Value = value;
Children = new List<Node>();
}
} public class GFG {
static Node FindRoot(List<Node> tree)
{
Dictionary<Node, Node> parents
= new Dictionary<Node, Node>();
// Iterate over each node and its children
foreach (Node node in tree)
{
foreach (Node child in node.Children)
{
parents[child] = node;
}
}
// Find the root node by checking for a node without
// a parent
foreach (Node node in tree)
{
if (!parents.ContainsKey(node)) {
return node;
}
}
// No root found
return null ;
}
public static void Main( string [] args)
{
// Create the nodes for the given example tree
Node node1 = new Node(5);
Node node2 = new Node(3);
Node node3 = new Node(6);
Node node4 = new Node(7);
Node node5 = new Node(9);
Node node6 = new Node(2);
Node node7 = new Node(1);
Node node8 = new Node(8);
// Define the relationships between the nodes
node1.Children.AddRange(
new [] { node2, node3, node4 });
node2.Children.AddRange( new [] { node5, node6 });
node4.Children.AddRange( new [] { node7, node8 });
// Create the list of nodes representing the tree
List<Node> tree
= new List<Node>{ node1, node2, node3, node4,
node5, node6, node7, node8 };
// Find the root of the tree
Node root = FindRoot(tree);
// Print the value of the root node
if (root != null ) {
Console.WriteLine($ "Root value: { root.Value }" );
}
else {
Console.WriteLine( "No root found." );
}
// Clean up the dynamically allocated nodes
foreach (Node node in tree)
{
// Since C# uses automatic memory management
// (garbage collection), manual memory
// deallocation (delete) is not necessary. The
// nodes will be automatically cleaned up when
// they are no longer referenced.
}
}
} // This code is contributed by Susobhan Akhuli |
<script> // Javascript program of the above approach class Node { constructor(value) {
this .value = value;
this .children = [];
}
} function findRoot(tree) {
const parents = new Map();
// Iterate over each node and its children
for (const node of tree) {
for (const child of node.children) {
parents.set(child, node);
}
}
// Find the root node by checking for a node without a parent
for (const node of tree) {
if (!parents.has(node)) {
return node;
}
}
// No root found
return null ;
} // Create the nodes for the given example tree const node1 = new Node(5);
const node2 = new Node(3);
const node3 = new Node(6);
const node4 = new Node(7);
const node5 = new Node(9);
const node6 = new Node(2);
const node7 = new Node(1);
const node8 = new Node(8);
// Define the relationships between the nodes node1.children = [node2, node3, node4]; node2.children = [node5, node6]; node4.children = [node7, node8]; // Create the array of nodes representing the tree const tree = [node1, node2, node3, node4, node5, node6, node7, node8]; // Find the root of the tree const root = findRoot(tree); // Print the value of the root node if (root) {
document.write( "Root value:" , root.value);
} else {
document.write( "No root found." );
} // Clean up the dynamically allocated nodes for (const node of tree) {
delete node;
} // This code is contributed by Susobhan Akhuli </script> |
Root value: 5
Time Complexity: O(N), where N is the number of nodes
Auxiliary Space: O(N) where N is the number of nodes