Height of a generic tree from parent array
Last Updated :
01 Nov, 2024
Given a tree of size n as array parent[0..n-1] where every index i in the parent[] represents a node and the value at i represents the immediate parent of that node. For root, the node value will be -1. Find the height of the generic tree given the parent links.
Examples:
Input: parent[] = [-1, 0, 0, 0, 3, 1, 1, 2]
Output : 2
Input: parent[] = [-1, 0, 1, 2, 3]
Output : 4
Here, a generic tree is sometimes also called an N-ary tree or N-way tree where N denotes the maximum number of child a node can have. In this problem, the array represents n number of nodes in the tree.
The naive approach is to traverse up the tree from the node till the root node is reached with node value -1. While Traversing for each node stores maximum path length. The Time Complexity of this solution is O(n^2).
[Expected Approach - 1] Using BFS - O(n) Time and O(n) Space
Build graph for N-ary Tree in O(n) time and apply BFS on the stored graph in O(n) time and while doing BFS store maximum reached level. This solution does two iterations to find the height of N-ary tree.
Below is the implementation of the above approach:
C++
// C++ code of finding height of N-array
// tree using BFS
#include <bits/stdc++.h>
using namespace std;
int buildTree(vector<int> &parent, int n,
vector<vector<int>> &adj) {
int root = -1;
// Iterate through all nodes to
//establish connections
for (int i = 0; i < n; i++) {
if (parent[i] == -1)
root = i;
else {
adj[i].push_back(parent[i]);
adj[parent[i]].push_back(i);
}
}
return root;
}
// Function to compute height of the tree
// using BFS
int getTreeHeight(int root,
vector<vector<int>> &adj) {
// Visited map to track nodes
map<int, bool> visited;
// Pair stores (node, level)
queue<pair<int, int>> q;
int maxHeight = 0;
// Start BFS from the
// root node
q.push({root, 0});
while (!q.empty()) {
auto node = q.front().first;
auto level = q.front().second;
q.pop();
visited[node] = true;
maxHeight = max(maxHeight, level);
// Traverse all children of the
// current node
for (int child : adj[node]) {
if (!visited[child]) {
// Increment level
q.push({child, level + 1});
}
}
}
return maxHeight;
}
int main() {
// Example: N-ary tree represented
// by parent array
vector<int> parent = {-1, 0, 0, 0, 3, 1, 1, 2};
int n = parent.size();
vector<vector<int>> adj(n);
int root = buildTree(parent, n, adj);
int height = getTreeHeight(root, adj);
cout << height << endl;
return 0;
}
Java
// Java code to find the height of an
// N-ary tree using BFS
import java.util.*;
class GfG {
static int buildTree(int[] parent, int n,
List<List<Integer> > adj) {
int root = -1;
// Iterate through all nodes to establish
// connections
for (int i = 0; i < n; i++) {
if (parent[i] == -1)
root = i;
else {
adj.get(i).add(parent[i]);
adj.get(parent[i]).add(i);
}
}
return root;
}
// Function to compute height of the
// tree using BFS
static int getTreeHeight(int root,
List<List<Integer> > adj) {
Map<Integer, Boolean> visited = new HashMap<>();
Queue<int[]> q = new LinkedList<>();
int maxHeight = 0;
// Start BFS from the root node
q.add(new int[] { root, 0 });
while (!q.isEmpty()) {
int node = q.peek()[0];
int level = q.peek()[1];
q.poll();
visited.put(node, true);
maxHeight = Math.max(maxHeight, level);
// Traverse all children of the
// current node
for (int child : adj.get(node)) {
if (!visited.getOrDefault(child, false)) {
q.add(new int[] { child, level + 1 });
}
}
}
return maxHeight;
}
public static void main(String[] args) {
int[] parent = { -1, 0, 0, 0, 3, 1, 1, 2 };
int n = parent.length;
List<List<Integer> > adj = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
adj.add(new ArrayList<>());
}
int root = buildTree(parent, n, adj);
int height = getTreeHeight(root, adj);
System.out.println(height);
}
}
Python
# Python code to find the height of an
# N-ary tree using BFS
from collections import deque, defaultdict
def build_tree(parent):
adj = defaultdict(list)
root = -1
# Iterate through all nodes to
# establish connections
for i, p in enumerate(parent):
if p == -1:
root = i
else:
adj[i].append(p)
adj[p].append(i)
return root, adj
# Function to compute height of the
# tree using BFS
def get_tree_height(root, adj):
visited = set()
q = deque([(root, 0)])
max_height = 0
# Start BFS from the root node
while q:
node, level = q.popleft()
visited.add(node)
max_height = max(max_height, level)
# Traverse all children of the
# current node
for child in adj[node]:
if child not in visited:
# Increment level
q.append((child, level + 1))
return max_height
parent = [-1, 0, 0, 0, 3, 1, 1, 2]
root, adj = build_tree(parent)
height = get_tree_height(root, adj)
print(height)
C#
// C# code to find the height of an
// N-ary tree using BFS
using System;
using System.Collections.Generic;
class GfG {
static int BuildTree(int[] parent, int n,
List<List<int> > adj) {
int root = -1;
// Iterate through all nodes to establish
// connections
for (int i = 0; i < n; i++) {
if (parent[i] == -1)
root = i;
else {
adj[i].Add(parent[i]);
adj[parent[i]].Add(i);
}
}
return root;
}
// Function to compute height of the
// tree using BFS
static int GetTreeHeight(int root, List<List<int> > adj) {
var visited = new Dictionary<int, bool>();
var q = new Queue<(int, int)>();
int maxHeight = 0;
// Start BFS from the root node
q.Enqueue((root, 0));
while (q.Count > 0) {
var(node, level) = q.Dequeue();
visited[node] = true;
maxHeight = Math.Max(maxHeight, level);
// Traverse all children of the
// current node
foreach(int child in adj[node]) {
if (!visited.ContainsKey(child)
|| !visited[child]) {
q.Enqueue((child, level + 1));
}
}
}
return maxHeight;
}
static void Main(string[] args) {
int[] parent = { -1, 0, 0, 0, 3, 1, 1, 2 };
int n = parent.Length;
List<List<int> > adj = new List<List<int> >(n);
for (int i = 0; i < n; i++) {
adj.Add(new List<int>());
}
int root = BuildTree(parent, n, adj);
int height = GetTreeHeight(root, adj);
Console.WriteLine(height);
}
}
JavaScript
// JavaScript code to find the height of an N-ary tree using
// BFS
function buildTree(parent) {
let adj
= Array.from({length : parent.length}, () => []);
let root = -1;
// Iterate through all nodes to establish
// connections
for (let i = 0; i < parent.length; i++) {
if (parent[i] === -1)
root = i;
else {
adj[i].push(parent[i]);
adj[parent[i]].push(i);
}
}
return {root, adj};
}
// Function to compute height of the
// tree using BFS
function getTreeHeight(root, adj) {
let visited = new Set();
let q = [ [ root, 0 ] ];
let maxHeight = 0;
// Start BFS from the root node
while (q.length) {
let [node, level] = q.shift();
visited.add(node);
maxHeight = Math.max(maxHeight, level);
// Traverse all children of the
// current node
for (let child of adj[node]) {
if (!visited.has(child)) {
// Increment level
q.push([ child, level + 1 ]);
}
}
}
return maxHeight;
}
const parent = [ -1, 0, 0, 0, 3, 1, 1, 2 ];
const {root, adj} = buildTree(parent);
const height = getTreeHeight(root, adj);
console.log(height);
[Expected Approach - 2] Without using map - O(n) Time and O(n) Space
We can find the height of the N-ary Tree in only one iteration. We visit nodes from 0 to n-1 iteratively and mark the unvisited ancestors recursively if they are not visited before till we reach a node which is visited, or we reach the root node. If we reach the visited node while traversing up the tree using parent links, then we use its height and will not go further in recursion.
Explanation For Example 1:
- For node 0: Check for Root node is true,
Return 0 as height, Mark node 0 as visited - For node 1: Recur for an immediate ancestor, i.e 0, which is already visited
So, Use its height and return height(node 0) +1
Mark node 1 as visited - For node 2: Recur for an immediate ancestor, i.e 0, which is already visited
So, Use its height and return height(node 0) +1
Mark node 2 as visited - For node 3: Recur for an immediate ancestor, i.e 0, which is already visited
So, Use its height and return height(node 0) +1
Mark node 3 as visited - For node 4: Recur for an immediate ancestor, i.e 3, which is already visited
So, Use its height and return height(node 3) +1
Mark node 3 as visited - For node 5: Recur for an immediate ancestor, i.e 1, which is already visited
So, Use its height and return height(node 1) +1
Mark node 5 as visited - For node 6: Recur for an immediate ancestor, i.e 1, which is already visited
So, Use its height and return height(node 1) +1
Mark node 6 as visited - For node 7: Recur for an immediate ancestor, i.e 2, which is already visited
So, Use its height and return height(node 2) +1 - Mark node 7 as visited
Hence, we processed each node in the N-ary tree only once.
Below is the implementation of the above approach:
C++
// C++ code of finding height of N-array
// tree
#include <bits/stdc++.h>
using namespace std;
// Recur For Ancestors of node and
// store height of node at last
int fillHeight(vector<int> &parent, int node,
vector<int> &visited, vector<int> &height) {
// If root node
if (parent[node] == -1) {
// mark root node as visited
visited[node] = 1;
return 0;
}
// If node is already visited
if (visited[node])
return height[node];
// Visit node and calculate its
// height
visited[node] = 1;
// Recur for the parent node
height[node] = 1 + fillHeight(parent,
parent[node], visited, height);
// Return calculated height for node
return height[node];
}
int findHeight(vector<int> &parent) {
int n = parent.size();
// To store max height
int maxHeight = 0;
// To check whether or not node is
// visited before
vector<int> visited(n, 0);
// For storing the height of each node
vector<int> height(n, 0);
// Calculate the height of all nodes
for (int i = 0; i < n; i++) {
// If not visited before
if (!visited[i])
height[i] = fillHeight(parent, i, visited, height);
// Store maximum height so far
maxHeight = max(maxHeight, height[i]);
}
return maxHeight;
}
int main() {
vector<int> parent = {-1, 0, 0, 0, 3, 1, 1, 2};
cout << findHeight(parent) << endl;
return 0;
}
Java
// Java code of finding height of N-array
// tree
import java.util.*;
class GfG {
// Recur For Ancestors of node and store height of node
// at last
static int fillHeight(List<Integer> parent, int node,
List<Integer> visited,
List<Integer> height) {
// If root node
if (parent.get(node) == -1) {
// mark root node as visited
visited.set(node, 1);
return 0;
}
// If node is already visited
if (visited.get(node) == 1)
return height.get(node);
// Visit node and calculate its height
visited.set(node, 1);
// Recur for the parent node
height.set(node, 1 + fillHeight(parent,
parent.get(node),
visited, height));
// Return calculated height
// for node
return height.get(node);
}
static int findHeight(List<Integer> parent) {
int n = parent.size();
// To store max height
int maxHeight = 0;
// To check whether or not node is
// visited before
List<Integer> visited
= new ArrayList<>(Collections.nCopies(n, 0));
// For storing the height of each node
List<Integer> height
= new ArrayList<>(Collections.nCopies(n, 0));
// Calculate the height of all nodes
for (int i = 0; i < n; i++) {
// If not visited before
if (visited.get(i) == 0)
height.set(i, fillHeight(parent, i, visited,
height));
// Store maximum height so far
maxHeight = Math.max(maxHeight, height.get(i));
}
return maxHeight;
}
public static void main(String[] args) {
List<Integer> parent
= Arrays.asList(-1, 0, 0, 0, 3, 1, 1, 2);
System.out.println(findHeight(parent));
}
}
Python
# Python code of finding height of N-array
# tree
def fillHeight(parent, node, visited, height):
# If root node
if parent[node] == -1:
# mark root node as visited
visited[node] = 1
return 0
# If node is already visited
if visited[node]:
return height[node]
# Visit node and calculate its height
visited[node] = 1
# Recur for the parent node
height[node] = 1 + fillHeight(parent, \
parent[node], visited, height)
# Return calculated height for node
return height[node]
def findHeight(parent):
n = len(parent)
# To store max height
maxHeight = 0
# To check whether or not node is
# visited before
visited = [0] * n
# For storing the height of each node
height = [0] * n
# Calculate the height of all nodes
for i in range(n):
# If not visited before
if not visited[i]:
height[i] = fillHeight(parent, i, \
visited, height)
# Store maximum height so far
maxHeight = max(maxHeight, height[i])
return maxHeight
if __name__ == "__main__":
parent = [-1, 0, 0, 0, 3, 1, 1, 2]
print(findHeight(parent))
C#
// C# code of finding height of N-array
// tree
using System;
using System.Collections.Generic;
class GfG {
// Recur For Ancestors of node and store height of node
// at last
static int FillHeight(List<int> parent, int node,
List<int> visited,
List<int> height) {
// If root node
if (parent[node] == -1) {
// mark root node as visited
visited[node] = 1;
return 0;
}
// If node is already visited
if (visited[node] == 1)
return height[node];
// Visit node and calculate
// its height
visited[node] = 1;
// Recur for the parent node
height[node] = 1 + FillHeight(parent, parent[node],
visited, height);
// Return calculated height for node
return height[node];
}
static int FindHeight(List<int> parent) {
int n = parent.Count;
// To store max height
int maxHeight = 0;
// To check whether or not node is visited before
List<int> visited = new List<int>(new int[n]);
// For storing the height of each node
List<int> height = new List<int>(new int[n]);
// Calculate the height of all nodes
for (int i = 0; i < n; i++) {
// If not visited before
if (visited[i] == 0)
height[i] = FillHeight(parent, i, visited,
height);
// Store maximum height so far
maxHeight = Math.Max(maxHeight, height[i]);
}
return maxHeight;
}
static void Main(string[] args) {
List<int> parent
= new List<int>{ -1, 0, 0, 0, 3, 1, 1, 2 };
Console.WriteLine(FindHeight(parent));
}
}
JavaScript
// Javascript code of finding height of N-array
// tree
function fillHeight(parent, node, visited, height) {
// If root node
if (parent[node] === -1) {
// mark root node as visited
visited[node] = 1;
return 0;
}
// If node is already visited
if (visited[node])
return height[node];
// Visit node and calculate its height
visited[node] = 1;
// Recur for the parent node
height[node] = 1
+ fillHeight(parent, parent[node],
visited, height);
// Return calculated height for node
return height[node];
}
function findHeight(parent) {
let n = parent.length;
// To store max height
let maxHeight = 0;
// To check whether or not node
// is visited before
let visited = Array(n).fill(0);
// For storing the height of each node
let height = Array(n).fill(0);
// Calculate the height of all nodes
for (let i = 0; i < n; i++) {
// If not visited before
if (!visited[i])
height[i]
= fillHeight(parent, i, visited, height);
// Store maximum height so far
maxHeight = Math.max(maxHeight, height[i]);
}
return maxHeight;
}
let parent = [ -1, 0, 0, 0, 3, 1, 1, 2 ];
console.log(findHeight(parent));
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem