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

height-of-a-generic-tree-from-parent-array-2

**Input: parent[] = [-1, 0, 1, 2, 3]
**Output : 4

height-of-a-generic-tree-from-parent-array

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

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, 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:

height-of-a-generic-tree-from-parent-array-2

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 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));

`