Given an N-ary tree, the task is to calculate the longest path between any two nodes (also known as the diameter of the tree).
Examples:
Example1: The diameter of the N-ary tree in the below example is 9, which represents the number of edges along the path marked with green nodes.
Example2: The diameter of the N-ary tree in the below example is 7, which represents the number of edges along the path marked with green nodes.
Approach:
The idea is to use Dynamic Programming with two key states: dp1[node] and dp2[node]. The value dp1[node] represents the longest path from the current node to any leaf in its subtree, while dp2[node] represents the longest path passing through the current node and two of its subtrees. By combining these two states across all nodes, we compute the maximum diameter. A Depth First Search (DFS) traversal is used to calculate these states efficiently.
Step-by-step approach:
Use dp1[node] (longest path to a leaf in subtree) and dp2[node] (longest path passing through the node and its two subtrees).
For leaf nodes, set dp1[node] = 0 and dp2[node] = 0.
Begin a DFS traversal from an arbitrary node, tracking the parent to avoid revisits.
For each node, find the two largest dp1[child] values using firstMaxand secondMax.
Update the diameter as the maximum of dp2[node] and the current diameter.
C++
// C++ program to find the diameter// of n-ary tree using dp.#include<bits/stdc++.h>usingnamespacestd;classNode{public:intdata;vector<Node*>children;Node(intx){data=x;}};// Function to perform DFS and calculate dp1 and dp2intdfs(Node*node,unordered_map<Node*,int>&dp1,unordered_map<Node*,int>&dp2,int&diameter){if(!node)return0;intfirstMax=-1,secondMax=-1;// Traverse children of the current nodefor(Node*child:node->children){// Recursive call to process childdfs(child,dp1,dp2,diameter);// Find first and second maximum dp1 valuesif(dp1[child]>firstMax){secondMax=firstMax;firstMax=dp1[child];}elseif(dp1[child]>secondMax){secondMax=dp1[child];}}// Calculate dp1[node] and dp2[node]dp1[node]=1+(firstMax==-1?0:firstMax);dp2[node]=(firstMax==-1?0:firstMax)+(secondMax==-1?0:secondMax);// Update diameterdiameter=max(diameter,dp2[node]);returndp1[node];}// Function to calculate the diameter of the treeintdiameter(Node*root){if(!root)return0;unordered_map<Node*,int>dp1,dp2;intdiameter=0;// Call DFS to calculate diameterdfs(root,dp1,dp2,diameter);returndiameter;}intmain(){// Hard coded tree // 1// / \ // 2 3 // / \ // 4 5Node*root=newNode(1);Node*node2=newNode(2);Node*node3=newNode(3);Node*node4=newNode(4);Node*node5=newNode(5);root->children.push_back(node2);root->children.push_back(node3);node2->children.push_back(node4);node2->children.push_back(node5);cout<<diameter(root)<<endl;return0;}
Java
// Java program to find the diameter// of n-ary tree using dp.importjava.util.*;classNode{intdata;List<Node>children;Node(intx){data=x;children=newArrayList<>();}}classGfG{// Function to perform DFS and calculate dp1 and dp2staticintdfs(Nodenode,Map<Node,Integer>dp1,Map<Node,Integer>dp2,int[]diameter){if(node==null)return0;intfirstMax=-1,secondMax=-1;// Traverse children of the current nodefor(Nodechild:node.children){// Recursive call to process childdfs(child,dp1,dp2,diameter);// Find first and second maximum dp1 valuesif(dp1.getOrDefault(child,0)>firstMax){secondMax=firstMax;firstMax=dp1.getOrDefault(child,0);}elseif(dp1.getOrDefault(child,0)>secondMax){secondMax=dp1.getOrDefault(child,0);}}// Calculate dp1[node] and dp2[node]dp1.put(node,1+(firstMax==-1?0:firstMax));dp2.put(node,(firstMax==-1?0:firstMax)+(secondMax==-1?0:secondMax));// Update diameterdiameter[0]=Math.max(diameter[0],dp2.getOrDefault(node,0));returndp1.get(node);}// Function to calculate the diameter of the treestaticintdiameter(Noderoot){if(root==null)return0;Map<Node,Integer>dp1=newHashMap<>();Map<Node,Integer>dp2=newHashMap<>();int[]diameter=newint[1];// Call DFS to calculate diameterdfs(root,dp1,dp2,diameter);returndiameter[0];}publicstaticvoidmain(String[]args){// Hard coded tree// 1// / \// 2 3// / \// 4 5Noderoot=newNode(1);Nodenode2=newNode(2);Nodenode3=newNode(3);Nodenode4=newNode(4);Nodenode5=newNode(5);root.children.add(node2);root.children.add(node3);node2.children.add(node4);node2.children.add(node5);System.out.println(diameter(root));}}
Python
# Python program to find the diameter# of n-ary tree using dp.classNode:def__init__(self,x):self.data=xself.children=[]# Function to perform DFS and calculate dp1 and dp2defdfs(node,dp1,dp2,diameter):ifnotnode:return0firstMax=-1secondMax=-1# Traverse children of the current nodeforchildinnode.children:# Recursive call to process childdfs(child,dp1,dp2,diameter)# Find first and second maximum dp1 valuesifdp1.get(child,0)>firstMax:secondMax=firstMaxfirstMax=dp1.get(child,0)elifdp1.get(child,0)>secondMax:secondMax=dp1.get(child,0)# Calculate dp1[node] and dp2[node]dp1[node]=1+(0iffirstMax==-1elsefirstMax)dp2[node]=(0iffirstMax==-1elsefirstMax)+ \
(0ifsecondMax==-1elsesecondMax)# Update diameterdiameter[0]=max(diameter[0],dp2[node])returndp1[node]# Function to calculate the diameter of the treedefdiameter(root):ifnotroot:return0dp1={}dp2={}diameter=[0]# Call DFS to calculate diameterdfs(root,dp1,dp2,diameter)returndiameter[0]if__name__=="__main__":# Hard coded tree# 1# / \# 2 3# / \# 4 5root=Node(1)node2=Node(2)node3=Node(3)node4=Node(4)node5=Node(5)root.children.extend([node2,node3])node2.children.extend([node4,node5])print(diameter(root))
C#
// C# program to find the diameter// of n-ary tree using dp.usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicList<Node>children;publicNode(intx){data=x;children=newList<Node>();}}classGfG{// Function to perform DFS and calculate dp1 and dp2staticintdfs(Nodenode,Dictionary<Node,int>dp1,Dictionary<Node,int>dp2,refintdiameter){if(node==null)return0;intfirstMax=-1,secondMax=-1;// Traverse children of the current nodeforeach(Nodechildinnode.children){// Recursive call to process childdfs(child,dp1,dp2,refdiameter);// Find first and second maximum dp1 valuesif(dp1.ContainsKey(child)&&dp1[child]>firstMax){secondMax=firstMax;firstMax=dp1[child];}elseif(dp1.ContainsKey(child)&&dp1[child]>secondMax){secondMax=dp1[child];}}// Calculate dp1[node] and dp2[node]dp1[node]=1+(firstMax==-1?0:firstMax);dp2[node]=(firstMax==-1?0:firstMax)+(secondMax==-1?0:secondMax);// Update diameterdiameter=Math.Max(diameter,dp2[node]);returndp1[node];}// Function to calculate the diameter of the treestaticintdiameter(Noderoot){if(root==null)return0;Dictionary<Node,int>dp1=newDictionary<Node,int>();Dictionary<Node,int>dp2=newDictionary<Node,int>();intdiameter=0;// Call DFS to calculate diameterdfs(root,dp1,dp2,refdiameter);returndiameter;}staticvoidMain(string[]args){// Hard coded tree// 1// / \// 2 3// / \// 4 5Noderoot=newNode(1);Nodenode2=newNode(2);Nodenode3=newNode(3);Nodenode4=newNode(4);Nodenode5=newNode(5);root.children.Add(node2);root.children.Add(node3);node2.children.Add(node4);node2.children.Add(node5);Console.WriteLine(diameter(root));}}
JavaScript
// JavaScript program to find the diameter// of n-ary tree using dp.classNode{constructor(x){this.data=x;this.children=[];}}// Function to perform DFS and calculate dp1 and dp2functiondfs(node,dp1,dp2,diameter){if(!node)return0;letfirstMax=-1,secondMax=-1;// Traverse children of the current nodefor(constchildofnode.children){// Recursive call to process childdfs(child,dp1,dp2,diameter);// Find first and second maximum dp1 valuesif((dp1[child]||0)>firstMax){secondMax=firstMax;firstMax=dp1[child]||0;}elseif((dp1[child]||0)>secondMax){secondMax=dp1[child]||0;}}// Calculate dp1[node] and dp2[node]dp1[node]=1+(firstMax===-1?0:firstMax);dp2[node]=(firstMax===-1?0:firstMax)+(secondMax===-1?0:secondMax);// Update diameterdiameter[0]=Math.max(diameter[0],dp2[node]);returndp1[node];}// Function to calculate the diameter of the treefunctiondiameter(root){if(!root)return0;letdp1={};letdp2={};letdiameter=[0];// Call DFS to calculate diameterdfs(root,dp1,dp2,diameter);returndiameter[0];}// Hard coded tree// 1// / \// 2 3// / \// 4 5constroot=newNode(1);constnode2=newNode(2);constnode3=newNode(3);constnode4=newNode(4);constnode5=newNode(5);root.children.push(node2,node3);node2.children.push(node4,node5);console.log(diameter(root));
Output
3
Time Complexity: O(n), where n is the total number of nodes in the tree. Auxiliary Space: O(n)