Diameter Of a N-Ary Tree
Problem
Given a root of an N-ary tree, you need to compute the length of the diameter of the tree.
The diameter of an N-ary tree is the length of the longest path between any two nodes in the tree. This path may or may not pass through the root.
(Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value.)
Examples
Example 1
graph TD A(1) A --- B(3) A --- C(2) A --- D(4) B(3) --- E(5) B(3) --- F(6) linkStyle 0 stroke:#FF0000,stroke-width:2px; linkStyle 1 stroke:#FF0000,stroke-width:2px; linkStyle 3 stroke:#FF0000,stroke-width:2px;
Input: root = [1,null,3,2,4,null,5,6]
Output: 3
Explanation: Diameter is shown in red color.
Example 2
graph TD A(1) --- B(2) B --- C(3) & D(4) C --- E(5) D --- F(6) classDef hidden display:none linkStyle 1 stroke:#FF0000,stroke-width:2px; linkStyle 2 stroke:#FF0000,stroke-width:2px; linkStyle 3 stroke:#FF0000,stroke-width:2px; linkStyle 4 stroke:#FF0000,stroke-width:2px;
Input: root = [1,null,2,null,3,4,null,5,null,6]
Output: 4
Example 3
graph TD A(1) A --- B(2) & C(3) & D(4) & E(5) C --- F(6) & G(7) D --- H(8) --- L(12) G --- K(11) --- N(14) E --- I(9) & J(10) I --- M(13) linkStyle 1 stroke:#FF0000,stroke-width:2px; linkStyle 2 stroke:#FF0000,stroke-width:2px; linkStyle 5 stroke:#FF0000,stroke-width:2px; linkStyle 6 stroke:#FF0000,stroke-width:2px; linkStyle 8 stroke:#FF0000,stroke-width:2px; linkStyle 9 stroke:#FF0000,stroke-width:2px; linkStyle 7 stroke:#FF0000,stroke-width:2px;
Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
Output: 7
Similar Problem
[Diameter Of a Binary Tree](diameter-of-a-binary-tree)
Solution
Definition of Diameter: The diameter of the tree is the longest path between any two nodes. This path may or may not pass through the root. Hence, we need to compute the longest paths in the subtree of each node.
Method 1 - DFS
We can use a recursive function to traverse through child nodes and calculate the heights.
Here is the approach:
- Start from the root and recursively calculate the heights of the subtrees of all child nodes.
- The height of a node is defined as the longest path from the node to any leaf.
- For each node, calculate the longest two heights among its children (let's call them
h1andh2). - The local diameter at a node will be
h1 + h2. - Update the global diameter (
ans) to be the maximum of the current global diameter and the local diameter.
- pick any node u
- find the node which is farthest from u, call it x (calculate using the same approach as in Solution 1)
- find the node which is farthest from x, call it q (calculate using the same approach as in Solution 1)
The answer will be the length of a path from x to q.
Code
Java
class Node {
public int val;
public List<Node> children;
public Node(int val) {
this.val = val;
this.children = new ArrayList<>();
}
}
public class Solution {
int ans = 0; // Global variable to track the maximum diameter
public int diameter(Node root) {
dfs(root);
return ans;
}
private int dfs(Node node) {
if (node == null) return 0;
// List to store heights of all child nodes
List<Integer> heights = new ArrayList<>();
for (Node child : node.children) {
heights.add(dfs(child));
}
// Sort heights in descending order
heights.sort(Collections.reverseOrder());
// Get the two largest heights
int h1 = heights.size() > 0 ? heights.get(0) : 0;
int h2 = heights.size() > 1 ? heights.get(1) : 0;
// Update the global diameter
ans = Math.max(ans, h1 + h2);
// Return the height of the current node
return h1 + 1;
}
}
Python
class Node:
def __init__(self, val: int, children: Optional[List['Node']] = None):
self.val = val
self.children = children if children else []
class Solution:
def diameter(self, root: Optional[Node]) -> int:
ans = 0 # Global variable to keep track of the maximum diameter
def dfs(node: Optional[Node]) -> int:
nonlocal ans # Access the global `ans` inside this function
if not node:
return 0
# Collect heights of all child nodes
heights = [dfs(child) for child in node.children]
heights.sort(reverse=True) # Sort the heights in descending order
# Take the two largest heights for computing the diameter
h1 = heights[0] if len(heights) > 0 else 0
h2 = heights[1] if len(heights) > 1 else 0
# Update the global diameter
ans = max(ans, h1 + h2)
# Return the height of the current node
return h1 + 1
dfs(root) # Start the DFS from the root
return ans
Complexity
- ⏰ Time complexity:
O(n)- Each node of the tree is visited exactly once. Calculating heights and updating the global diameter also takes constant time per node. Hence, the traversal takes
O(n).
- Each node of the tree is visited exactly once. Calculating heights and updating the global diameter also takes constant time per node. Hence, the traversal takes
- 🧺 Space complexity:
O(h)- The recursion stack can go as deep as the height
hof the tree in the worst case. Therefore, the space complexity isO(h).
- The recursion stack can go as deep as the height