The diameter is the longest path between any two nodes, measured in edges.
The path does NOT have to pass through the root — check every node.
At each node, compute left_child_height + right_child_height as a candidate.
Use a single DFS to compute subtree heights while updating a global max.
Time O(n), space O(h) — but watch for stack overflow on skewed trees.
Most common mistake: summing heights from root only, missing deeper paths.
✦ Definition~90s read
What is Diameter of Binary Tree?
The diameter of a binary tree is the length of the longest path between any two nodes measured in number of edges. The path does not need to pass through the root. Think of the tree as a set of roads connecting nodes; the diameter is the longest road trip you can take without backtracking.
★
Imagine a tree where you want to find the two most distant leaves.
For a tree with just a root, diameter = 0. For a tree where the deepest left subtree has height 3 and the deepest right subtree has height 2, the longest path through the root has 3+2=5 edges. But the actual diameter might be in a subtree entirely on the left side if that subtree itself spans a longer path.
The key insight is that at every node, the longest path passing through that node equals left_height + right_height.
Plain-English First
Imagine a tree where you want to find the two most distant leaves. The diameter is the number of steps (edges) between them. You can find it by checking every fork in the tree and seeing how far you can go left and right, then keeping the biggest distance.
Binary tree diameter problems appear in routing optimization, phylogenetic analysis, and distributed systems where longest-path metrics determine latency bounds. The naive root-only calculation fails in production because it ignores paths that live entirely within subtrees—right-skewed trees silently return wrong answers. This article shows why the single-pass DFS approach is the standard in production codebases, with explicit trace-throughs and the edge cases that break naive implementations.
What is the Diameter of a Binary Tree? — Plain English
The diameter of a binary tree is the length of the longest path between any two nodes measured in number of edges. The path does not need to pass through the root. Think of the tree as a set of roads connecting nodes; the diameter is the longest road trip you can take without backtracking. For a tree with just a root, diameter = 0. For a tree where the deepest left subtree has height 3 and the deepest right subtree has height 2, the longest path through the root has 3+2=5 edges. But the actual diameter might be in a subtree entirely on the left side if that subtree itself spans a longer path. The key insight is that at every node, the longest path passing through that node equals left_height + right_height.
Mental Model
Longest Path as 'Double Height'
Think of the diameter through a node as the sum of the longest downward paths to leaves on its left and right.
For each node, imagine you're standing there and can walk down two different branches.
The distance you can cover is left_height + right_height steps.
The global diameter is the maximum possible such walk across all nodes.
This works because any path in a tree has a highest node — the one closest to the root.
📊 Production Insight
If you only compute heights from the root, you'll miss the true diameter.
We saw a production pipeline that underestimated batch processing times by 30% because it assumed the longest dependency chain always started at the root.
Always evaluate every node: the bottleneck might be buried deep in a subtree.
🎯 Key Takeaway
Diameter is max(left_height + right_height) across ALL nodes.
Don't fixate on the root — the longest path can bypass it entirely.
The answer is always an edge count, not node count.
Do I need to compute diameter?
IfTree is empty (root is None)
→
UseReturn 0 (or -1 by some definitions — clarify in your API).
IfTree has a single node
→
UseDiameter = 0 (no edges between nodes).
IfTree is a straight line (each node has one child)
→
UseDiameter = number_of_edges, which equals height of the tree.
IfTree is balanced with branching
→
UseDiameter may be through the root or a subtree — compute global max.
thecodeforge.io
Diameter Binary Tree
How Diameter of Binary Tree Works — Step by Step
Use a recursive DFS that returns the height of each subtree while updating a global maximum.
Define a helper dfs(node) that returns the height of the subtree rooted at node.
Base case: if node is None, return -1 (height of empty tree is -1, so a single leaf has height 0).
Recursively compute left_h = dfs(node.left) and right_h = dfs(node.right).
The diameter candidate at this node = left_h + right_h + 2 (add 2 for the two edges connecting to children).
Return max(left,right) + 1 as the height of current node.
Run the example: node with two children → candidate = 0+0+2 = 2, correct for 3-node tree.
Naive O(n²) Approach — Why It Fails and How to Improve
Before diving into the optimal O(n) solution, it's instructive to examine the naive approach that many developers write first. The naive solution computes the height of each node separately for every node, leading to O(n²) time. For each node, it calls a separate height function that traverses all descendants. The diameter candidate is simply left_height(node) + right_height(node), and we take the maximum across all nodes. While this is conceptually simple, it's painfully slow for large trees. Each height computation takes O(n) in the worst case, and we do it for all n nodes, resulting in O(n²). The optimal solution solves the problem in a single DFS by combining height calculation with diameter tracking.
naive_diameter.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
defheight(node):
if node isNone:
return -1return1 + max(height(node.left), height(node.right))
defdiameter_naive(root):
if root isNone:
return0# Compute height of left and right subtrees
left_h = height(root.left) + 1if root.left else0
right_h = height(root.right) + 1if root.right else0# Diameter through root
through_root = left_h + right_h
# Recur for subtrees
left_diameter = diameter_naive(root.left)
right_diameter = diameter_naive(root.right)
returnmax(through_root, left_diameter, right_diameter)
# Usage with tree from earlier example
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(diameter_naive(root)) # Correctly prints 3, but O(n²)
Output
3
⚠ Why naive is not for production
The naive solution recomputes height multiple times for the same subtree. In a balanced tree of 1000 nodes, that's about 1 million height calls. For a skewed tree with 1000 nodes, it's about 500,000 calls but each height takes O(n) — total O(n²) ≈ 1,000,000 operations. The O(n) solution does exactly n calls.
📊 Production Insight
In production, you'll rarely have trees small enough to make O(n²) tolerable. A tree with 10,000 nodes would require ~50 million node visits (naive) vs 10,000 (optimal). Always challenge yourself to write the linear solution — it's a common interview differentiator and a sign of production-readiness.
🎯 Key Takeaway
Naive O(n²) solution computes height separately for each node. Optimal O(n) combines height and diameter tracking in one DFS. Write the naive only for pedagogical understanding — never deploy it.
Final diameter=3. Path: 4→2→1→3 (or 5→2→1→3). Both have 3 edges.
📊 Production Insight
Walking through this trace by hand catches 90% of implementation bugs.
When you're debugging, annotate each recursive call's candidate and current diameter.
Production teams often skip this step — that's how off-by-one errors sneak into code that runs in production for months.
🎯 Key Takeaway
Trace with a small balanced tree first.
Candidate at node 2 is 2 (left+right+2), at root 1 is 3.
Global diameter = max over all candidates = 3.
The path goes through node 2? No — actually through root 1, but only because the deepest point is left of 2.
Visual Tree Diagram — Diameter Path Highlighted
The diagram below shows the tree used in the worked example. The diameter path from node 4 to node 3 is highlighted in red. This path goes up from 4 to 2, then to root 1, then down to 3. It covers exactly 3 edges. Understanding how the path traverses through the highest node (the root in this case, but it could be any node) reinforces the "every node as potential apex" concept.
📊 Production Insight
Visualizations like this help during code reviews or when explaining to a team. If your production tree is too large to visualize, consider using tools like graphviz or d3.js to render and inspect the diameter path programmatically. Debugging via visual feedback is often faster than tracing logs.
🎯 Key Takeaway
The diameter path always has a highest node (apex). In this example it is the root, but in skewed trees it may be a deeper node.
Binary tree with diameter path highlighted (nodes 4 → 2 → 1 → 3, 3 edges)
Implementation
The solution uses a single DFS traversal. A class-level or nonlocal variable tracks the running maximum diameter. At each node, compute left and right subtree heights recursively, update the diameter with left_h + right_h + 2, then return max(left_h, right_h) + 1 as the node's height. The solution runs in O(n) time and O(h) stack space where h is the tree height (O(log n) balanced, O(n) worst case for skewed trees).
diameter_binary_tree.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
classTreeNode:
def__init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
defdiameter_of_binary_tree(root):
diameter = [0] # use list to allow mutation in nested functiondefdfs(node):
if node isNone:
return -1
left_h = dfs(node.left)
right_h = dfs(node.right)
# path through this node has (left_h+1) + (right_h+1) edges
diameter[0] = max(diameter[0], left_h + right_h + 2)
returnmax(left_h, right_h) + 1dfs(root)
return diameter[0]
# Build tree: 1->2->4,5 and 1->3
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(diameter_of_binary_tree(root)) # 3 (path 4->2->1->3)
Output
3
⚠ Watch the recursion depth in production
If your tree is highly skewed (like a linked list), the recursion depth equals the number of nodes. Python's default recursion limit may cause RecursionError. For production systems, consider an iterative post-order traversal using an explicit stack.
📊 Production Insight
Using a list to wrap the integer is a Python trick to allow mutation inside a nested function.
In Java you'd use a class field or an int[] array.
The space complexity O(h) can become O(n) for skewed trees — that's when you hit stack overflow.
We've seen this crash a nightly batch job processing deep organizational hierarchies.
🎯 Key Takeaway
Single-pass DFS: O(n) time, O(h) space.
Use a mutable container (list, array) for the global max.
For production code on deep trees, prefer iterative implementation.
C++ Implementation
The C++ implementation follows the same logic: a recursive helper returns height while updating a diameter variable passed by reference. The key difference is the explicit use of std::max and the struct for TreeNode. C++ recursion depth is also limited by the call stack; for very deep trees, consider an iterative approach using a stack of pairs or a post-order traversal with parent pointers.
C++ is often preferred in latency-sensitive production environments (e.g., game engines, real-time systems). The same recursion depth concerns apply — on Linux the default stack size is 8 MB, which can accommodate roughly 2000–8000 recursive calls depending on frame size. For trees deeper than that, use an explicit stack or switch to iterative post-order.
🎯 Key Takeaway
C++ implementation mirrors Python logic. Use reference parameter to update diameter. Be wary of stack depth on deep trees; iterative version recommended for production.
Top-Down Recursion Approach — Alternative Implementation Pattern
Instead of using a global variable, the top-down approach returns a pair (height, diameter) from each node. This is a more functional style, avoids global state, and is easier to parallelize (though tree recursion doesn’t parallelize trivially). The function computes the left and right pair recursively, then constructs the current node's pair: height = max(left.height, right.height) + 1, diameter = max(left.diameter, right.diameter, left.height + right.height + 2). The top-down pattern is especially useful when the problem can be expressed as combining results from children without side effects.
Both approaches are functionally equivalent and run in O(n). The top-down version avoids global variables and is theoretically cleaner, but some developers find the bottom-up (global max) easier to reason about. Choose whichever aligns with your team's coding standards.
📊 Production Insight
In a production codebase, consistency matters more than elegance. If your team already uses global variables for tracking state in tree traversals (e.g., for width, depth, or sum), stick with the bottom-up pattern. But if you're building a library where thread-safety is a concern, the top-down approach (no mutation) is safer — though you'll still need to handle recursion depth.
🎯 Key Takeaway
Top-down returns (height, diameter) pair from each node, avoiding global state. Both patterns O(n) — pick based on codebase style and thread-safety needs.
Edge Cases and Production Pitfalls
Beyond the basic algorithm, you need to handle
Empty tree: Return 0 or -1? Clarify the definition – edge length between nonexistent nodes is typically 0.
Single node: Height is 0, diameter is 0.
Two nodes: Root and one child – diameter is 1 (one edge).
Very deep tree (skewed): Recursion depth equals number of nodes. Use iterative solution.
Large balanced tree: Recursion depth ~ log n (safe).
Tree with negative values? Not relevant, diameter counts edges not node values.
Memory constraints: For huge trees, you might need to serialize and process chunks.
📊 Production Insight
The most common production bug we see is the 0-vs-(-1) base case debate.
One team defined empty height as 0, leading to double-counting on leaves.
Another team used node count instead of edge count – their diameter was always one more than correct.
Always validate with a trivial tree: root with left child only → expected diameter = 1.
🎯 Key Takeaway
Test with empty, single, two-node, and skewed trees.
Base case of -1 simplifies leaf height to 0 and makes candidate = left+right+2.
Edge count vs node count: if you ever get confused, remember that diameter between two leaves has (number of nodes - 1) edges.
Advantages and Disadvantages of the O(n) Diameter Algorithm
Recursion stack depth — can overflow for skewed trees unless converted to iterative.
Single-pass — computes height and diameter simultaneously.
Global or non-local state — the bottom-up approach requires a mutable variable.
Handles any tree shape — balanced, skewed, arbitrary — always correct.
Not trivial to parallelize — tree recursion is sequential by nature.
Low constant factor — simple arithmetic operations per node.
Base case confusion — using 0 instead of -1 leads to off-by-one errors.
Well-documented — widely used in textbooks and interviews.
May require adaptation for weighted edges — edge weights would change the formula.
The algorithm is optimal for the problem. The disadvantages are manageable with careful implementation: use iterative approach for deep trees, and validate base cases through unit tests.
📊 Production Insight
When evaluating whether to use this algorithm in production, consider the tree's shape distribution. If your data tends to be shallow (e.g., organizational hierarchies depth < 100), recursion is fine. If you have deep chains (e.g., file system paths), invest in the iterative version upfront.
🎯 Key Takeaway
O(n) time, O(h) space. Main downsides: recursion depth and base-case sensitivity. Both solvable with iterative approach and careful testing.
Practice Problems
Reinforce your understanding by solving these related problems:
[LeetCode 543 — Diameter of Binary Tree](https://leetcode.com/problems/diameter-of-binary-tree/) — The classic problem, identical to this article.
[LeetCode 687 — Longest Univalue Path](https://leetcode.com/problems/longest-univalue-path/) — Similar concept but path must consist of nodes with the same value.
[LeetCode 124 — Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/) — Uses similar pattern but with node values.
[LeetCode 1522 — Diameter of N-Ary Tree](https://leetcode.com/problems/diameter-of-n-ary-tree/) — Extend the idea to trees with multiple children.
[GeeksforGeeks — Diameter of a Tree](https://www.geeksforgeeks.org/diameter-of-a-binary-tree/) — Additional explanations and variations.
[LeetCode 298 — Binary Tree Longest Consecutive Sequence](https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/) — Another path-length problem that uses DFS with state tracking.
📊 Production Insight
Practicing these problems will make the pattern second nature. In my experience, teams that have solved all five are significantly faster at adapting the pattern to non-tree problems (like finding the longest path in a DAG).
🎯 Key Takeaway
Master diameter by practicing its variants: same value, max sum, n-ary trees. The recursive pattern generalizes to many tree path problems.
The Naive O(n²) Approach: Why Your First Attempt Will Fail in Production
Most devs start by computing height at every node — simple and obviously correct. At each node, you calculate left height and right height via recursive calls, update the diameter candidate, and recurse into children. Problem solved for a toy tree of 10 nodes.
But here's the trap: every height call recursively walks its entire subtree. For a node at depth d, you compute its subtree's height, then compute again for its parent, then again for its grandparent. Those heights get recomputed O(n) times across the recursion. Total cost balloons to O(n²) — fine for a balanced tree of 1000 nodes, but a degenerate tree (essentially a linked list) with 100,000 nodes? You're now chewing through 10 billion operations. Your monitoring dashboard will show a timeout alert before you finish debugging.
The space complexity is O(h) for the recursion stack, which is fine. The time complexity is the killer. Don't ship this to production unless you enjoy explaining to your CTO why a simple tree query took four seconds.
Never compute height separately for each node. It's the classic O(n²) gotcha that slips through code reviews because it looks clean. Always track height and diameter in a single pass.
🎯 Key Takeaway
Always compute height and diameter together in one traversal — never recompute height from scratch per node.
thecodeforge.io
Diameter Binary Tree
The O(n) Single Traversal: One Pass, No Regrets
The fix is dead simple: compute height and diameter in the same recursive pass. Your recursive function returns the height of the subtree, but before returning, it updates a global or mutable reference tracking the maximum diameter seen. No redundant recalculations. Each node is visited exactly once.
The insight? The diameter at any node is just the sum of its left and right subtree heights. The height of the node itself is 1 + max(leftHeight, rightHeight). If you return height from recursion, you get both values for free. Capture the max diameter as a side effect — a simple class field or an int[1] array passed by reference.
Time complexity drops to O(n) — every node touched precisely once. Space is still O(h) for the recursion stack, which is optimal for any recursive tree traversal. For a degenerate tree of 100k nodes, that's 100k operations, not 10 billion. The numbers don't lie. This is the version that goes to production.
Use a mutable int[] array instead of a class field if you want thread-safety in recursive calls. Or pass an AtomicInteger if you hate yourself.
🎯 Key Takeaway
One traversal, one height function, one global max — that's the production-grade pattern for tree diameter.
● Production incidentPOST-MORTEMseverity: high
Wrong Diameter in a Production Analytics Pipeline
Symptom
User-facing analytics showed consistently lower tree diameters than expected. Manual inspection of known trees gave correct values, but the system reported smaller numbers for deeply nested hierarchies.
Assumption
The team assumed the longest path always passes through the root.
Root cause
The algorithm computed left_height(root) + right_height(root) and returned that value. It never evaluated subtrees independently. In a right-skewed tree with a deep left-right internal branch, the true diameter lay entirely inside the right subtree.
Fix
Replaced the naive function with the recursive DFS that updates a global maximum at every node. Now the algorithm correctly captures diameters that bypass the root.
Key lesson
Never assume the path goes through the root — update the max at every node.
Always test with lopsided trees and edge cases like single-node trees.
Recursive solutions should be paired with a stack-limit check to avoid overflow.
Production debug guideCommon pitfalls and how to fix them fast4 entries
Symptom · 01
Returned value is too small (always a single branch length)
→
Fix
Check if you're only computing height and not updating a global diameter variable. Ensure you call max(diameter, left_h + right_h + 2) at each node.
Symptom · 02
Stack overflow on large trees
→
Fix
Convert recursive DFS to iterative post-order traversal using explicit stack. Or increase the recursion limit (sys.setrecursionlimit) but prefer iteration for production.
Symptom · 03
Off-by-one: result is one more or one less than expected
→
Fix
Verify base case: height of empty subtree should be -1, so a leaf contributes 0 height. Then candidate = left_h + right_h + 2 (two edges to children). If you use 0 for empty, you'll overcount.
Symptom · 04
Global variable not reset between test cases
→
Fix
In a testing framework, ensure the global diameter variable is re-initialized for each tree. Better yet, wrap the logic in a class or use a mutable container (e.g., array) to avoid static state.
★ Diameter Debug Quick ReferenceDiagnose diameter issues in seconds
Result is 0 for a tree with more than 0 nodes−
Immediate action
Check if base case returns 0 instead of -1 for None.
Trace with a small tree (3 nodes, root with left and right child). Expected diameter = 2.
Fix now
Set base case to -1 and candidate to left_h + right_h + 2.
Result changes between runs (non-deterministic)+
Immediate action
Check if global variable is static and not reset.
Commands
Add diameter = 0 before each dfs call.
Use a mutable object (like a list) passed as parameter to avoid global state.
Fix now
Encapsulate dfs inside a function that reinitializes diameter.
Stack overflow with RecursionError+
Immediate action
Check tree height; if > 1000, recursion may exceed Python default limit.
Commands
sys.getrecursionlimit() to see current limit.
sys.setrecursionlimit(10000) temporarily, but plan iterative fix.
Fix now
Rewrite using explicit stack (iterative post-order) or increase limit with caution.
Diameter vs Height vs Longest Path in Weighted Tree
Metric
Definition
Algorithm
Complexity
Height
Longest path from root to leaf
Single DFS: max(left,right)+1
O(n), O(h)
Diameter (unweighted)
Longest path between any two nodes (edges)
DFS + global max of left+right+2
O(n), O(h)
Diameter (weighted)
Longest weighted path between nodes
DFS returning max path sum with two children (like max path sum)
O(n), O(h)
Max Path Sum (node values)
Maximum sum of node values along a path
DFS returning left+right+node, update global max
O(n), O(h)
⚙ Quick Reference
6 commands from this guide
File
Command / Code
Purpose
naive_diameter.py
def height(node):
Naive O(n²) Approach
diameter_binary_tree.py
class TreeNode:
Implementation
diameter_binary_tree.cpp
using namespace std;
C++ Implementation
diameter_top_down.py
def diameter_top_down(root):
Top-Down Recursion Approach
DiameterBruteForce.java
class DiameterBruteForce {
The Naive O(n²) Approach
DiameterEfficient.java
class DiameterEfficient {
The O(n) Single Traversal
Key takeaways
1
The diameter equals the maximum over all nodes of (left_subtree_height + right_subtree_height + 2).
2
A single DFS can compute diameter in O(n) by returning height at each node while updating a global max.
3
Never assume the longest path passes through the root
update the max at every node.
4
Base case
empty subtree height = -1 to make leaf height = 0.
5
Test with a simple tree
root + two children → expected diameter = 2 edges.
Common mistakes to avoid
5 patterns
×
Assuming the diameter always passes through the root
Symptom
The function only computes left_height + right_height at the root and returns that. For trees where the real diameter is deeper, the result is too small.
Fix
Use a global variable updated at every node during DFS. The candidate at each node is left_h + right_h + 2.
×
Using 0 instead of -1 for empty subtree height
Symptom
Leaf nodes get height 1 instead of 0. Candidate becomes (1 + 1 + 2) = 4 for a three-node tree that should have diameter 2. All results are off by 2.
Fix
Set base case to -1: if node is None, return -1. Then leaf height = 0, and candidate = -1 + -1 + 2 = 0 for leaf. For a node with two children, candidate = 0+0+2 = 2 (correct).
×
Confusing node count with edge count
Symptom
Result is always 1 more than expected. For a two-node tree, returns 1 node count instead of 1 edge. For three-node chain, returns 2 instead of 2? Actually edges = nodes-1, so if you count nodes you overcount by 1.
Fix
Always define diameter as number of edges. The formula left_h+right_h+2 adds two edges connecting children. Validate with a simple chain of 3 nodes: height = 2, diameter = 2 (edges between farthest nodes).
×
Forgetting to handle empty tree or single node specially
Symptom
Code crashes with None access or returns unexpected value (e.g., -1 from base case).
Fix
Handle empty root: return 0. Single node: return 0. Base case should return -1 for None is fine as long as you treat the final result correctly. Many implementations wrap the DFS in a function that returns max(0, result) for empty.
×
Using global/static variable without resetting between test cases
Symptom
Running multiple tests in the same session yields incorrect increasing diameters.
Fix
Reset the global diameter variable before each test. Alternatively, pass a mutable container (e.g., a list) as parameter to the DFS function to isolate state.
What is the time complexity of finding the diameter?
Q04SENIOR
Write the code to compute the diameter of a binary tree.
Q05SENIOR
How would you handle a very deep tree to avoid stack overflow?
Q01 of 05JUNIOR
What is the diameter of a binary tree?
ANSWER
The diameter (or width) of a binary tree is the length of the longest path between any two nodes in the tree, measured by the number of edges. The path may or may not pass through the root. It is computed by considering every node as a potential highest point of the path and summing the heights of its left and right subtrees.
Q02 of 05SENIOR
Why can the diameter path bypass the root?
ANSWER
Because the longest path between two nodes might be entirely contained within a subtree. For example, in a tree where the root has only a right child, which itself has two deep branches, the longest path lies within that right child's subtree and never touches the root. Our algorithm must evaluate candidate diameters at every node, not just the root.
Q03 of 05JUNIOR
What is the time complexity of finding the diameter?
ANSWER
O(n) time because we visit each node exactly once during the DFS. The space complexity is O(h) for the recursion stack, where h is the height of the tree (O(log n) for balanced, O(n) for skewed). In production systems, stack overflow for skewed trees may require an iterative solution.
Q04 of 05SENIOR
Write the code to compute the diameter of a binary tree.
ANSWER
The typical solution uses a recursive DFS that returns the height while updating a global maximum. In Python:
def diameter_of_binary_tree(root):
diameter = 0
def dfs(node):
nonlocal diameter
if not node:
return -1
left = dfs(node.left)
right = dfs(node.right)
diameter = max(diameter, left + right + 2)
return max(left, right) + 1
dfs(root)
return diameter
This handles empty trees (returns 0) and computes O(n).
Q05 of 05SENIOR
How would you handle a very deep tree to avoid stack overflow?
ANSWER
For production code, convert the recursive DFS to an iterative post-order traversal using an explicit stack. Each stack frame stores the node and a state (0 = left not visited, 1 = right not visited). Maintain a dictionary or second stack for computed heights. This uses O(n) space in worst case but avoids recursion depth limits. Alternatively, increase the recursion limit if you control the environment and tree depth is bounded.
01
What is the diameter of a binary tree?
JUNIOR
02
Why can the diameter path bypass the root?
SENIOR
03
What is the time complexity of finding the diameter?
JUNIOR
04
Write the code to compute the diameter of a binary tree.
SENIOR
05
How would you handle a very deep tree to avoid stack overflow?
SENIOR
FAQ · 5 QUESTIONS
Frequently Asked Questions
01
Why is the diameter not always the path through the root?
Consider a lopsided tree where the root has only a right child, which itself has a very deep left and right subtree. The longest path is entirely within the right subtree and never touches the root. By updating the diameter at every node during DFS, we capture the maximum path regardless of which node it passes through.
Was this helpful?
02
What is the time complexity of the diameter algorithm?
O(n) time because DFS visits each node exactly once. O(h) space for the recursive call stack where h is the height. For a balanced tree h = O(log n); for a skewed (pathological) tree h = O(n).
Was this helpful?
03
How does this differ from finding the height of a binary tree?
Height is the longest path from root to any leaf — a single recursive DFS returning max(left,right)+1. Diameter is the longest path between any two nodes, which may pass through any node. Diameter requires tracking a global maximum updated at each node with left_height + right_height.
Was this helpful?
04
Should I return 0 or -1 for an empty tree?
The diameter of an empty tree by most definitions is 0 (no nodes, no edges). However, the base case for height must return -1 so that leaf height becomes 0. So your wrapper function should return 0 for a None root, but the recursive DFS uses -1 for None. Both are correct if the outer function handles the empty case.
Was this helpful?
05
What is the difference between diameter and 'longest path' in a tree?
Diameter is a specific type of longest path: it's the longest path between any two nodes in an unweighted tree. For weighted trees, the longest path might use edge weights, and the algorithm changes to a two-DFS approach or a variation that returns maximum weighted sum through a node.