Algorithm

All Nodes Distance K in Binary Tree

Trees Pattern

All Nodes Distance K in Binary Tree

Given the root of a binary tree, a target node, and an integer k, return the values of every node whose distance from the target is exactly k. Distance is the number of edges on the path between two nodes, and edges may be travelled in either direction — so a node above the target counts just as much as one below it. The answer may be returned in any order, and is empty if no node is that far away.

CONSTRAINTS
  • The number of nodes in the tree is in the range [1, 500]
  • 0 <= Node.val <= 500, and all values are unique
  • target is guaranteed to be a node of the tree
  • 0 <= k <= 1000, so k may exceed the tree's reach
EXAMPLE 1
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2
Output: [7,4,1]
7 and 4 lie two steps below the target through node 2. Node 1 is two steps away going *upward* — from 5 to the root 3, then down to 1 — which is why downward-only reasoning misses it.
EXAMPLE 2
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 0
Output: [5]
Zero steps away means the target itself. It is a legitimate input rather than an edge case to reject.
EXAMPLE 3
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 3
Output: [0,8]
Three steps: up to the root, down to 1, then to either of its children. Every node at this distance is reached by first travelling upward.
EXAMPLE 4
Input: root = [1], target = 1, k = 5
Output: []
Nothing is that far away, so the answer is an empty list — k is allowed to exceed the tree's reach.
Does distance count upward moves?
Yes. The path may climb toward the root and descend again, which is precisely what makes this harder than a depth-limited descent.
Is the order of values in the return array important?
No, any order is accepted.
Is target given as a node or as a value?
Usually the node object. If only a value is given, locate the node first — an extra traversal, and one that relies on the values being unique.
What if k is larger than the tree?
Return an empty list. The search exhausts every reachable node before reaching ring k.

If the question were "which nodes are k steps below the target", it would be a short recursion: descend k levels and collect whatever you land on. The difficulty is that distance here is measured along edges travelled in either direction, so the answer can include the target's parent, its grandparent, and whole subtrees hanging off ancestors — regions no downward walk from the target ever reaches.

The links only point one way

The obstacle is structural rather than conceptual. Each node holds pointers to its children and nothing else, so from the target we can go down but never up. That asymmetry is a fact about our representation, not about the problem: the edge between a parent and a child is perfectly symmetric, and the question treats it that way. We are simply missing half of every edge.

Restore the missing half, and it becomes a graph

So add what is missing. Walk the tree once and record, for every node, who its parent is — a map from node to parent, with the root mapping to nothing. Now every node has up to three neighbours: left child, right child, and parent.

At that point the tree stops mattering. What we have is an undirected graph — nodes joined by two-way edges — and "which nodes are exactly k edges from this one" is the standard graph question of expanding outward in rings: everything one edge away, then everything two edges away, and so on. Breadth-first search from the target does exactly that, and the ring reached on step k is the answer.

There is one new obligation compared with tree traversals. In a tree, moving away from the root can never revisit a node, so no bookkeeping is needed. With two-way edges you can walk straight back where you came from — target to parent, parent back to target — looping forever and reporting nodes at the wrong distance. So keep a visited set and admit each node once, on its first arrival. Because breadth-first search reaches a node along its shortest path first, that first arrival is at the node's true distance, which makes blocking later arrivals both safe and necessary.

python
parent = {}
def map_parents(node, par):
    if node is None: return
    parent[node] = par
    map_parents(node.left, node)
    map_parents(node.right, node)
map_parents(root, None)

queue, seen, dist = deque([target]), {target}, 0
while queue:
    if dist == k:
        return [n.val for n in queue]      # this entire ring is exactly k away
    for _ in range(len(queue)):            # frozen ring size — expand one ring at a time
        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)
    dist += 1
return []
Crucial Notethe visited set is not an optimisation, it is what makes the distances correct. Without it, the target's parent would immediately re-enqueue the target, which would reappear in the ring at distance 2 and re-expand its whole subtree at inflated distances — an answer that is wrong, not merely slow. Whenever you convert a tree into a graph by adding edges, the no-revisit guarantee you were silently relying on disappears and has to be replaced explicitly.

The frozen len(queue) is the same level-boundary device from Binary Tree Level Order Traversal, doing the same job — except that here a "level" is a ring of equal distance rather than a row of the tree.

Worked example:root 3, children 5 and 1; 5 has children 6 and 2; 2 has children 7 and 4; 1 has children 0 and 8. Target 5, k = 2
- The parent map records 5 → 3, 6 → 5, 2 → 5, 7 → 2, 4 → 2, 1 → 3, 0 → 1, 8 → 1, and 3 → nothing.
- Ring 0: the queue holds [5]. Not yet k, so expand its three neighbours — children 6 and 2, and parent 3. All unseen, all enqueued.
- Ring 1: the queue holds [6, 2, 3]. Not yet k. Node 6 has no children and its parent 5 is already seen, so it contributes nothing. Node 2 adds its children 7 and 4. Node 3 adds its right child 1 — its left child 5 is seen, and it has no parent.
- Ring 2: the queue holds [7, 4, 1], and dist now equals k. Return [7, 4, 1].

Node 1 is the payoff: it was reached by going up from 5 to 3 and then down again, a route the original pointers made impossible. And node 5 never reappeared, because the visited set stopped 3 from walking back into it.

Cost, and the reframing to keep

Building the parent map visits every node once, and the search admits every node at most once, so the total is O(N) time with O(N) space for the map, the visited set and the queue.

The move worth remembering is the reframing itself: when a tree problem needs to travel upward, stop treating it as a tree and turn it into a graph. Add the parent edges, then apply whichever graph algorithm the question actually wants — breadth-first search for distances, depth-first for reachability. Spotting this early converts a family of awkward-looking tree problems into standard graph exercises, and the next problem, Amount of Time for Binary Tree to Be Infected, is the same construction with a different question asked of the same rings.

Interactive Strategy Visualization

Nodes at Distance K

Multi-Directional BFS from Target

351620874
Target: Node 5, K = 2
Starting BFS from target node...

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.
BFS WAVESTEP 0/4
Initialize BFS from target node 5.
USE CASE

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"

Downward-Only DFS (Misses Ancestors)
O(N) Time · O(N) Space Parent Map Plus Ring-by-Ring BFS