DP on Trees | Set3 ( Diameter of Nary Tree ) (original) (raw)

DP on Trees | Set-3 ( Diameter of N-ary Tree )

Last Updated : 11 Jul, 2025

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.

diameter---------of---------a---------n---------array---------tree

**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.

diameter---------of---------a---------n---------array---------tree---------2

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

// C++ program to find the diameter // of n-ary tree using dp. #include <bits/stdc++.h> using namespace std;

class Node { public: int data; vector<Node*> children;

Node(int x) {
    data = x;
}

};

// Function to perform DFS and calculate dp1 and dp2 int dfs(Node* node, unordered_map<Node*, int>& dp1, unordered_map<Node*, int>& dp2, int& diameter) { if (!node) return 0;

int firstMax = -1, secondMax = -1;

// Traverse children of the current node
for (Node* child : node->children) {
    
    // Recursive call to process child
    dfs(child, dp1, dp2, diameter);

    // Find first and second maximum dp1 values
    if (dp1[child] > firstMax) {
        secondMax = firstMax;
        firstMax = dp1[child];
    } 
    else if (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 diameter
diameter = max(diameter, dp2[node]);

return dp1[node];

}

// Function to calculate the diameter of the tree int diameter(Node* root) { if (!root) return 0;

unordered_map<Node*, int> dp1, dp2;
int diameter = 0;

// Call DFS to calculate diameter
dfs(root, dp1, dp2, diameter);

return diameter;

}

int main() {

// Hard coded tree 
//          1
//         / \
//        2   3 
//       / \
//      4   5
Node* root = new Node(1);
Node* node2 = new Node(2);
Node* node3 = new Node(3);
Node* node4 = new Node(4);
Node* node5 = new Node(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;

return 0;

}

Java

// Java program to find the diameter // of n-ary tree using dp. import java.util.*;

class Node { int data; List children;

Node(int x) {
    data = x;
    children = new ArrayList<>();
}

}

class GfG {

// Function to perform DFS and calculate dp1 and dp2
static int dfs(Node node, Map<Node, Integer> dp1, 
Map<Node, Integer> dp2, int[] diameter) {
    if (node == null) return 0;

    int firstMax = -1, secondMax = -1;

    // Traverse children of the current node
    for (Node child : node.children) {

        // Recursive call to process child
        dfs(child, dp1, dp2, diameter);

        // Find first and second maximum dp1 values
        if (dp1.getOrDefault(child, 0) > firstMax) {
            secondMax = firstMax;
            firstMax = dp1.getOrDefault(child, 0);
        } 
        else if (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 diameter
    diameter[0] = Math.max(diameter[0], 
    dp2.getOrDefault(node, 0));

    return dp1.get(node);
}

// Function to calculate the diameter of the tree
static int diameter(Node root) {
    if (root == null) return 0;

    Map<Node, Integer> dp1 = new HashMap<>();
    Map<Node, Integer> dp2 = new HashMap<>();
    int[] diameter = new int[1];

    // Call DFS to calculate diameter
    dfs(root, dp1, dp2, diameter);

    return diameter[0];
}

public static void main(String[] args) {

    // Hard coded tree
    //          1
    //         / \
    //        2   3
    //       / \
    //      4   5
    Node root = new Node(1);
    Node node2 = new Node(2);
    Node node3 = new Node(3);
    Node node4 = new Node(4);
    Node node5 = new Node(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.

class Node: def init(self, x): self.data = x self.children = []

Function to perform DFS and calculate dp1 and dp2

def dfs(node, dp1, dp2, diameter): if not node: return 0

firstMax = -1
secondMax = -1

# Traverse children of the current node
for child in node.children:

    # Recursive call to process child
    dfs(child, dp1, dp2, diameter)

    # Find first and second maximum dp1 values
    if dp1.get(child, 0) > firstMax:
        secondMax = firstMax
        firstMax = dp1.get(child, 0)
    elif dp1.get(child, 0) > secondMax:
        secondMax = dp1.get(child, 0)

# Calculate dp1[node] and dp2[node]
dp1[node] = 1 + (0 if firstMax == -1 else firstMax)
dp2[node] = (0 if firstMax == -1 else firstMax) + \
(0 if secondMax == -1 else secondMax)

# Update diameter
diameter[0] = max(diameter[0], dp2[node])

return dp1[node]

Function to calculate the diameter of the tree

def diameter(root): if not root: return 0

dp1 = {}
dp2 = {}
diameter = [0]

# Call DFS to calculate diameter
dfs(root, dp1, dp2, diameter)

return diameter[0]

if name == "main":

# Hard coded tree
#          1
#         / \
#        2   3
#       / \
#      4   5
root = 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. using System; using System.Collections.Generic;

class Node { public int data; public List children;

public Node(int x) {
    data = x;
    children = new List<Node>();
}

}

class GfG {

// Function to perform DFS and calculate dp1 and dp2
static int dfs(Node node, Dictionary<Node, int> dp1, 
Dictionary<Node, int> dp2, ref int diameter) {
    if (node == null) return 0;

    int firstMax = -1, secondMax = -1;

    // Traverse children of the current node
    foreach (Node child in node.children) {

        // Recursive call to process child
        dfs(child, dp1, dp2, ref diameter);

        // Find first and second maximum dp1 values
        if (dp1.ContainsKey(child) && dp1[child] > firstMax) {
            secondMax = firstMax;
            firstMax = dp1[child];
        } else if (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 diameter
    diameter = Math.Max(diameter, dp2[node]);

    return dp1[node];
}

// Function to calculate the diameter of the tree
static int diameter(Node root) {
    if (root == null) return 0;

    Dictionary<Node, int> dp1 = new Dictionary<Node, int>();
    Dictionary<Node, int> dp2 = new Dictionary<Node, int>();
    int diameter = 0;

    // Call DFS to calculate diameter
    dfs(root, dp1, dp2, ref diameter);

    return diameter;
}

static void Main(string[] args) {

    // Hard coded tree
    //          1
    //         / \
    //        2   3
    //       / \
    //      4   5
    Node root = new Node(1);
    Node node2 = new Node(2);
    Node node3 = new Node(3);
    Node node4 = new Node(4);
    Node node5 = new Node(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.

class Node { constructor(x) { this.data = x; this.children = []; } }

// Function to perform DFS and calculate dp1 and dp2 function dfs(node, dp1, dp2, diameter) { if (!node) return 0;

let firstMax = -1, secondMax = -1;

// Traverse children of the current node
for (const child of node.children) {

    // Recursive call to process child
    dfs(child, dp1, dp2, diameter);

    // Find first and second maximum dp1 values
    if ((dp1[child] || 0) > firstMax) {
        secondMax = firstMax;
        firstMax = dp1[child] || 0;
    } else if ((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 diameter
diameter[0] = Math.max(diameter[0], dp2[node]);

return dp1[node];

}

// Function to calculate the diameter of the tree function diameter(root) { if (!root) return 0;

let dp1 = {};
let dp2 = {};
let diameter = [0];

// Call DFS to calculate diameter
dfs(root, dp1, dp2, diameter);

return diameter[0];

}

// Hard coded tree // 1 // /
// 2 3 // /
// 4 5 const root = new Node(1); const node2 = new Node(2); const node3 = new Node(3); const node4 = new Node(4); const node5 = new Node(5); root.children.push(node2, node3); node2.children.push(node4, node5);

console.log(diameter(root));

`

**Time Complexity: O(n), where n is the total number of nodes in the tree.
**Auxiliary Space: O(n)

**Related articles: