Finding the Diameter of an N-Ary Tree: the "To-And-Thru" approach
Hello folks, this is a problem that exemplifies a technique that I like to call the To-And-Thru. We want to find the diameter of an N-ary tree (meaning a tree where each node has 0, 1 or more children). Take a look: https://leetcode.com/problems/diameter-of-n-ary-tree/
What you want is a near-linear solution in the number of nodes. If you assume that the tree has N nodes, and that each node has an average of LogN children, then the To-And-Thru algorithm below will run in O(N * (LogN)^2) time. Not really linear, but something that seems to be closer to NLogN.
The idea is the following:
- Post-Order DFS
- For each node, compute the following:
- The longest path TO the node
- The longest path THRU the node
- The above computation will take LogN*LogN since there are two nested loops (I guess there might be a way to reduce this to LogN, meaning one loop)
- As you compute 2.1 and 2.2, your diameter will be the Max
See figure below. Works well enough. Code is down below, stay safe, stay motivated!!! ACC
public class Solution {
public int Diameter(Node root)
{
int maxThruNode = 0;
int maxToNode = 0;
int diameter = 0;
Diameter(root, ref maxThruNode, ref maxToNode, ref diameter);
return diameter > 0 ? diameter - 1 : diameter; //I'm counting the number of nodes in the path. Number of edges is #nodes-1
}
private void Diameter(Node node,
ref int maxThruNode,
ref int maxToNode,
ref int diameter)
{
if (node == null) return;
if (node.children.Count == 0)
{
maxThruNode = 1;
maxToNode = 1;
return;
}
int[] childMaxThruNode = new int[node.children.Count];
int[] childMaxToNode = new int[node.children.Count];
int index = 0;
foreach (Node child in node.children)
{
Diameter(child, ref childMaxThruNode[index], ref childMaxToNode[index], ref diameter);
index++;
}
maxThruNode = 0;
maxToNode = 0;
for (int i = 0; i < childMaxThruNode.Length; i++)
{
maxToNode = Math.Max(childMaxToNode[i] + 1, maxToNode);
diameter = Math.Max(maxToNode, diameter);
for (int j = i + 1; j < childMaxThruNode.Length; j++)
{
maxThruNode = Math.Max(childMaxToNode[i] + childMaxToNode[j] + 1, maxThruNode);
maxToNode = Math.Max(childMaxToNode[i] + 1, maxToNode);
maxToNode = Math.Max(childMaxToNode[j] + 1, maxToNode);
diameter = Math.Max(maxThruNode, diameter);
diameter = Math.Max(maxToNode, diameter);
}
}
}
}
Comments
Post a Comment