[Medium] 863. All Nodes Distance K in Binary Tree
Difficulty: Medium
Category: Tree, DFS, BFS
Companies: Amazon, Facebook, Google, Microsoft, Apple
Given the root of a binary tree, the value of a target node, and an integer k, return an array of the values of all nodes that have a distance k from the target node.
You can return the answer in any order.
Examples
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2
Output: [7,4,1]
Explanation: The nodes that are a distance 2 from the target node (value 5) have values 7, 4, and 1.
Example 2:
Input: root = [1], target = 1, k = 3
Output: []
Constraints
- The number of nodes in the tree is in the range
[1, 500]. 0 <= Node.val <= 500- All the values
Node.valare unique. targetis the value of one of the nodes in the tree.k >= 0
Solution Approaches
Approach 1: Convert Tree to Graph with DFS
Key Insight: Convert the binary tree into an undirected graph, then perform BFS/DFS from the target node to find all nodes at distance k.
Algorithm:
- Build adjacency list by traversing the tree
- Store parent-child relationships bidirectionally
- Perform DFS starting from target node
- Track visited nodes to avoid cycles
- Collect nodes at exact distance k
Time Complexity: O(n)
Space Complexity: O(n)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
buildGraph(root, nullptr);
visited.insert(target->val);
dfs(target->val, 0, k);
return rtn;
}
private:
unordered_map<int, vector<int>> graph;
vector<int> rtn;
unordered_set<int> visited;
void buildGraph(TreeNode* curr, TreeNode* parent) {
if(curr && parent) {
graph[curr->val].push_back(parent->val);
graph[parent->val].push_back(curr->val);
}
if(curr->left) buildGraph(curr->left, curr);
if(curr->right) buildGraph(curr->right, curr);
}
void dfs(int curr, int dist, int K) {
if(dist == K) {
rtn.push_back(curr);
return;
}
for(int neighbor: graph[curr]) {
if(!visited.contains(neighbor)) {
visited.insert(neighbor);
dfs(neighbor, dist + 1, K);
}
}
}
};
Solution Explanation
Approach: Recursive DFS (this problem)
Key idea: Difficulty:** Medium
How the code works: Difficulty: Medium Category: Tree, DFS, BFS
- Model entities as nodes and relationships as edges.
- Pick traversal (BFS/DFS) or shortest-path (Dijkstra) based on weights.
- Union-Find helps when connectivity updates are frequent.
Walkthrough — input root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2, expected output [7,4,1]:
The nodes that are a distance 2 from the target node (value 5) have values 7, 4, and 1.
Implementation Details
Building Parent-Child Relationships
// Store bidirectional edges
if(curr && parent) {
graph[curr->val].push_back(parent->val);
graph[parent->val].push_back(curr->val);
}
DFS with Distance Control
void dfs(int curr, int dist, int K) {
if(dist == K) {
rtn.push_back(curr);
return;
}
// Recursively explore all neighbors
for(int neighbor: graph[curr]) {
if(!visited.contains(neighbor)) {
visited.insert(neighbor);
dfs(neighbor, dist + 1, K);
}
}
}
Three-Directional Search
// Explore: parent, left child, right child
dfs(parent[curr], dist - 1, rtn, visited);
dfs(curr->left, dist - 1, rtn, visited);
dfs(curr->right, dist - 1, rtn, visited);
Edge Cases
- Target is Root: Still works, no parent path
- k = 0: Returns only target node
- Single Node Tree: Returns empty array if k > 0
- k Beyond Tree Depth: Returns empty array
- Target at Leaf: Must go up to parent then down
Follow-up Questions
- What if the tree had more than 2 children per node?
- How would you modify for a directed graph?
- What if nodes could have duplicate values?
- How would you find nodes within distance k (not exactly k)?
Common Mistakes
- Skipping edge cases (empty input, single element, boundaries).
- Off-by-one errors in loops and index ranges.
- Forgetting to handle the case when no valid answer exists.
Related Problems
- LC 314: Binary Tree Vertical Order Traversal
- LC 863: All Nodes Distance K (This problem)
- LC 1161: Maximum Level Sum of a Binary Tree
- LC 742: Closest Leaf in a Binary Tree
Optimization Techniques
- Graph Conversion: O(n) one-time preprocessing
- Visited Tracking: O(1) lookup prevents redundant work
- Early Termination: Stop at distance k exactly
- Bidirectional Edges: Store parent-child relationships for undirected graph behavior
Code Quality Notes
- Clarity: Graph approach is most intuitive for new learners
- Modularity: Separate graph building from search logic
- Memory: Both approaches use O(n) space for n nodes
- Performance: All solutions are optimal O(n) time
This problem beautifully demonstrates how binary trees can be treated as graphs when we need multi-directional traversal capabilities.
Key Takeaways
- Pattern: Recursive DFS (this problem)
- Difficulty:** Medium
- Category:** Tree, DFS, BFS
References
- LC 863: All Nodes Distance K in Binary Tree on LeetCode
- LeetCode Discuss — LC 863: All Nodes Distance K in Binary Tree
- LeetCode Editorial (may require premium)
Template Reference
Thinking Process
Difficulty: Medium
Category: Tree, DFS, BFS
- Model entities as nodes and relationships as edges.
- Pick traversal (BFS/DFS) or shortest-path (Dijkstra) based on weights.
- Union-Find helps when connectivity updates are frequent.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Recursive DFS (this problem) | O(n) | O(h) stack | Natural for trees and graphs |
| Iterative DFS (stack) | O(n) | O(n) | Avoid recursion depth limits |
| DFS with memoization | O(n) | O(n) | Overlapping subproblems on graphs |
| Backtracking DFS | O(2^n) typical | O(n) | Enumerate choices with pruning |