Amount of Time for Binary Tree to Be Infected
An infection begins at minute 0 at the node whose value is start. Each minute, every already-infected node infects all of its immediate neighbours — its parent and both of its children. Return the number of minutes until every node in the tree is infected. If the tree has a single node, the answer is 0, since it is infected from the outset.
- The number of nodes is in the range [1, 10⁵]
- 1 <= Node.val <= 10⁵, and all values are unique
- start is guaranteed to be the value of a node in the tree
- Infection spreads to parents as well as to children
root = [1,5,3,null,4,10,6,9,2], start = 34root = [1], start = 10root = [1,2,null,3,null,4], start = 43root = [1,2,null,3,null,4], start = 32Forget the word "infection" for a moment — it is just a stopwatch on distance. A node lights up at minute d exactly when it sits d edges from the start, because the fire crawls one edge per minute in every direction at once. So the whole tree is on fire the moment the furthest node catches. The answer is simply the distance to that farthest node.
1
/ \
5 3 <-- start (minute 0)
\ / \
4 10 6
/ \
9 2
distances from 3: 10,6 -> 1 1 -> 1 5 -> 2 4 -> 3 9,2 -> 4
farthest is 9 and 2, four edges away -> answer = 4The catch is in that little diagram: the fire runs up from 3 to 1, then back down a whole different branch to reach 9 and 2. This is not tree depth measured from the root — it is spread outward from a node sitting anywhere in the tree.
Every node knows its children but not its parent. So from the start we can burn downward but never climb up to 1. Yet the edge between a parent and child is really two-way — we are just missing one direction. So add it: walk the tree once and write down each node's parent in a map. Now every node has up to three neighbours — left child, right child, and parent.
tree pointers (down only) + parent map = fire can go both ways
1 parent: 5->1, 3->1, 4->5,
/ \ 9->4, 2->4, 10->3, 6->3
5 3 start = 3 so from 3 the fire reaches
\ / \ 10, 6 (children) AND 1 (parent)
4 ...Once edges point both ways, the tree is really an undirected graph, and "how far is the farthest node" is the standard graph move: spread outward from the start in rings — everything 1 edge away, then everything 2 away — and keep going until the tree is exhausted. That is breadth-first search.
One duty comes with the two-way edges: you can walk straight back where you came from (3 → 1 → 3) and loop forever. So keep a visited set and admit each node only once, on first arrival. BFS always reaches a node by its shortest path first, so that first arrival is at its true distance — which makes blocking every later arrival both safe and necessary.
Ring 0 is the start alone, on fire at minute 0 — no time has passed yet. Ring 1 is on fire at minute 1, ring 2 at minute 2. So the answer is the minute of the last non-empty ring. Watch it run, start = 3:
minute 0: [3] burn -> children 10, 6 and parent 1
minute 1: [10, 6, 1] 10,6 add nothing new. 1 adds its child 5 (3 already seen)
minute 2: [5] 5 adds its child 4
minute 3: [4] 4 adds its children 9, 2
minute 4: [9, 2] both leaves, nothing new -> queue empties
last ring was minute 4 -> answer = 4parent, start_node = {}, None
def map_parents(node, par):
global start_node
if node is None: return
parent[node] = par
if node.val == start: start_node = node # find the start while mapping
map_parents(node.left, node)
map_parents(node.right, node)
map_parents(root, None)
queue, seen, minutes = deque([start_node]), {start_node}, -1
while queue:
minutes += 1 # ring 0 costs 0 minutes
for _ in range(len(queue)): # frozen ring size = one ring
node = queue.popleft()
for nxt in (node.left, node.right, parent[node]):
if nxt and nxt not in seen:
seen.add(nxt)
queue.append(nxt)
return minutesCrucial Note — the off-by-one is the whole game. minutes starts at -1 so that processing the first ring (the start by itself) bumps it to 0. Start it at 0 instead and every answer is one too big, including the single-node tree whose correct answer is 0. The clean way to never trip: fix the counter's meaning before the loop — here it is "the minute the ring being processed caught fire", which is 0 for the start.
The visited set is not an optimisation — it is what keeps distances correct. Drop it and node 1 would immediately re-enqueue node 3, which reappears a ring later at the wrong distance and re-burns its whole subtree with inflated numbers. Wrong answer, not merely a slow one.
Mapping parents visits every node once; BFS admits every node once. Total: O(N) time, O(N) space for the map, the visited set, and the queue. On the 10⁵-node limit a chain could push the recursive parent-mapping 10⁵ frames deep, so an iterative walk with an explicit stack is the safe version there.
Step back and notice how little was actually new. Once the parent edges exist, the tree is a graph, and this is the classic "how long does something spread through a network" question — answered by counting breadth-first layers. The same shape solves rotting oranges in a grid, shortest steps in a maze, and a rumour spreading through a social graph. Build the neighbour relation the question implies, expand outward in layers, and read off the last layer reached — and the tree is just one more graph.
Nodes at Distance K
Multi-Directional BFS from Target
Key Mechanics
- Parent Pointers: First, build a map of parent references to enable upward traversal.
- Multi-Directional: BFS explores left, right, and parent neighbors from the target.
- Distance Tracking: Each BFS level represents distance +1 from the target.
Real-World Applications
This pattern powers social network friend suggestions (find users K connections away), organizational hierarchy queries (employees K levels from a manager), and network routing (nodes K hops from a source). The parent-pointer technique transforms trees into undirected graphs for bidirectional exploration.
Strategy
Focus on the recursive nature of trees: solve for subtrees and combine results at the root.
"Divide and Conquer: Subproblem → Recurrence → Result"