Pattern #45
Tree Diameter
Important interview questions, thinking patterns, Postorder Height DFS, Subtree Diameter (Root exclusion), Two-Pass BFS trick, and Go code templates.
Must Solve
10 core questions — solve these first.
- 1.Diameter of Binary TreePostorder DFS: candidate = leftHeight + rightHeight, return 1 + max(leftHeight, rightHeight)easy
- 2.Diameter of N-ary TreeCollect height of all children, sum top 2 largest child heights for candidatemedium
- 3.Diameter of an Undirected TreeTwo BFS/DFS passes: BFS from arbitrary node to farthest A, then BFS from A to farthest Bmedium
- 4.Longest Path Between Any Two Tree NodesSame as Tree Diameter: track max path across all subtreesmedium
- 5.Binary Tree Maximum Path SumCandidate = node.Val + max(0, left) + max(0, right), return node.Val + max(0, max(left, right))hard
- 6.Longest Univalue PathPostorder DFS: extend path only if child.Val == node.Valmedium
- 7.Tree Diameter Using Two BFS / DFSTwo-pass algorithm: 1st search finds endpoint A, 2nd search finds endpoint B & distancemedium
- 8.Minimum Height TreesTrim leaf nodes layer-by-layer (Kahn algorithm / topological sort) until 1 or 2 centers remainmedium
- 9.Tree DistancesRerooting Tree DP: 1st DFS computes distances from root, 2nd DFS shifts root to children in O(1)hard
- 10.Farthest Node in a TreeRun BFS/DFS from target node to find node at max distancemedium
Also Important
5 more questions worth practicing.
- 11.Longest Path With Different Adjacent CharactersPostorder DFS: combine top 2 child branches where child.Char != node.Charhard
- 12.Longest ZigZag Path in a Binary TreeDFS tracking direction (0 for left, 1 for right) & current path lengthmedium
- 13.Maximum Path Between Two LeavesPostorder DFS: candidate updated ONLY at nodes with BOTH left and right children non-nilhard
- 14.Weighted Tree DiameterAccumulate edge weights instead of +1 per edge in two BFS/DFS passesmedium
- 15.Tree DP Longest Path VariantsPostorder state returns tracking longest and 2nd longest downward pathsmedium
How to Think
- Need longest path between any two nodes?Tree Diameter
- Binary Tree?Postorder DFS + Height
- At each node?leftHeight + rightHeight
- General undirected tree?Two BFS / DFS passes
Go Tree Diameter Templates
Binary Tree Diameter (Postorder DFS) & General Undirected Tree (Two-Pass BFS) in Go
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 1. Binary Tree Diameter (Single-Pass Postorder DFS)
func diameterOfBinaryTree(root *TreeNode) int {
maxDiameter := 0
var height func(node *TreeNode) int
height = func(node *TreeNode) int {
if node == nil {
return 0
}
leftH := height(node.Left)
rightH := height(node.Right)
// Update global diameter (uses BOTH branches!)
if leftH+rightH > maxDiameter {
maxDiameter = leftH + rightH
}
// Return height upward (returns ONE branch!)
return 1 + max(leftH, rightH)
}
height(root)
return maxDiameter
}
// 2. General Undirected Tree Diameter (Two BFS Passes)
func treeDiameterUndirected(n int, edges [][]int) int {
adj := make([][]int, n)
for _, e := range edges {
u, v := e[0], e[1]
adj[u] = append(adj[u], v)
adj[v] = append(adj[v], u)
}
bfs := func(start int) (int, int) {
dist := make([]int, n)
for i := range dist { dist[i] = -1 }
queue := []int{start}
dist[start] = 0
farthestNode, maxD := start, 0
for len(queue) > 0 {
curr := queue[0]
queue = queue[1:]
for _, neighbor := range adj[curr] {
if dist[neighbor] == -1 {
dist[neighbor] = dist[curr] + 1
if dist[neighbor] > maxD {
maxD = dist[neighbor]
farthestNode = neighbor
}
queue = append(queue, neighbor)
}
}
}
return farthestNode, maxD
}
farthestA, _ := bfs(0)
_, diameter := bfs(farthestA)
return diameter
}👉 Total Time: O(N) | Space: O(H) / O(N)
Height vs Diameter & Single-Pass DFS
1. Height: Distance from a node downward to its deepest leaf (1 + max(left, right)).
2. Diameter: Longest path between any two nodes in the tree (leftHeight + rightHeight).
3. Single-Pass DFS: Do NOT recalculate heights separately for each node (which causes O(N²) time)! Compute height once in a postorder DFS while updating a global diameter candidate.
Two-Pass BFS Trick for Undirected Trees
For general undirected trees represented as adjacency lists:
• Pass 1: Start at any arbitrary node X, run BFS to find the farthest node A (which is guaranteed to be one endpoint of a diameter).
• Pass 2: Start at node A, run BFS to find the farthest node B. The distance between A and B is the tree diameter!
Tree Diameter → Longest path between ANY two nodes (May NOT pass through Root!)
Binary Tree → Candidate = leftHeight + rightHeight | Return = 1 + max(left, right)
Edges vs Nodes → N nodes path = N-1 edges (Check problem definition!)
Undirected Tree → Two BFS passes (Arbitrary -> Farthest A -> Farthest B)💡 Golden Rule: "Each node asks: ‘What is the deepest path from my left, and what is the deepest path from my right?’ Their sum may be the diameter."
Common Interview Mistakes
The longest path in a tree can live entirely inside a subtree! You MUST update the global diameter candidate at every node during DFS.
A parent node cannot extend a path that splits into two directions! The DFS return value MUST be single-branch height (1 + max(left, right)).
Calling a separate height(node) helper inside a loop causes O(N²) time complexity! Compute height and diameter together in 1 pass.
A path of K nodes contains K - 1 edges. Check whether the problem asks for number of edges or number of nodes!
Interview Rules
- 1. Longest path between any two nodes? → Tree Diameter
- 2. Binary Tree strategy? → Postorder DFS returning height
- 3. Candidate diameter at node? →
leftHeight + rightHeight - 4. Return value upward to parent? →
1 + max(leftHeight, rightHeight) - 5. Passes through root? → Not necessarily! Update global max at every node
- 6. General undirected tree strategy?→ Two BFS/DFS passes (Arbitrary -> Farthest A -> Farthest B)
- 7. Max Path Sum comparison? → Max Path Sum sums node values; Diameter sums edge counts
- 8. Overall Complexity → Time:
O(N)| Stack Space:O(H)(O(log N)balanced,O(N)skewed)
Small Rules
- Rule 1: Tree Diameter is the longest path between any two nodes.
- Rule 2: Diameter does not need to pass through the root node.
- Rule 3: At every node, diameter candidate = leftHeight + rightHeight.
- Rule 4: DFS return value = 1 + max(leftHeight, rightHeight).
- Rule 5: Two BFS/DFS passes find diameter endpoints in general undirected trees.
Production Thinking
Network Topology Latency → Calculating worst-case hop count between any two nodes in a tree network
Organization Separation Distance → Measuring maximum managerial distance between two employees across departments
Dependency Separation Radius → Determining largest separation distance between two leaf package dependencies
Distributed Broadcast Bound → Finding maximum propagation delay for tree-structured broadcast topologies
Remember This
Tree Diameter → Longest path
Binary Tree → Postorder DFS
Left + Right → Candidate diameter
Return → 1 + max(left, right)
Global answer → Update everywhere
Root → Not necessarily on path
General Tree → BFS/DFS twice
Time → O(N)💡 Golden Rule: "Each node asks: ‘What is the deepest path from my left, and what is the deepest path from my right?’ Their sum may be the diameter."