Height of a generic tree from parent array (original) (raw)
Last Updated : 1 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).
Table of Content
- [Expected Approach - 1] Using BFS - O(n) Time and O(n) Space
- [Expected Approach - 2] Without using map - O(n) Time and O(n) Space
**[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 &parent, int n, vector<vector> &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> &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, adjFunction 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_heightparent = [-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 &parent, int node, vector &visited, vector &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 &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 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 maxHeightif 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));
`

