Binary Trees · 32 of 35
Find distance between 2 nodes in a Binary tree
Count the steps along the branches between two nodes of a tree, by finding where their paths up to the root meet.
- Simple way
- time O(n)
room O(h) - Clever way
- time O(n)
room O(h)
The problem, simply
You get a binary tree with all different values, and two values a and b that are both in the tree. Find the distance between them: the number of branches (edges) on the path from one to the other.
The path always goes up from a to some meeting node, then down to b. That meeting node is the lowest node that has both of them below it (or is one of them).
A story to remember it
Picture it
From 7 to 6: up 7, 5, 2 to the meeting point 1, then down 3 to 6. That is 3 steps up and 2 steps down, 5 edges in all.
- looking now
- answer
- path
Examples
Far apart
- In
tree = [1, 2, 3, 4, 5, null, 6, null, null, 7], a = 7, b = 6- Out
5
7, 5, 2, 1, 3, 6. They meet at the root.
Siblings
- In
same tree, a = 4, b = 5- Out
2
4, 2, 5. They meet at their parent 2.
One is above the other
- In
same tree, a = 2, b = 7- Out
2
2 is 7's grandparent, so the meeting point is 2 itself: 2, 5, 7.
The same node
- In
same tree, a = 4, b = 4- Out
0
No steps at all.
Two nodes
- In
tree = [1, 2], a = 1, b = 2- Out
1
One branch between them.
Way 1: the simple way
Write down the path from the root to a and the path from the root to b. They start the same and then split. The steps after the split are the answer.
- Find the path from the root to
a, as a list of nodes. - Find the path from the root to
b. - Count how many nodes the two lists share at the start,
i. - The distance is
(pathA.size() - i) + (pathB.size() - i).
import java.util.*;
class Solution {
public int findDist(TreeNode root, int a, int b) {
List<TreeNode> pa = new ArrayList<>(), pb = new ArrayList<>();
if (!path(root, a, pa) || !path(root, b, pb)) return -1; // not found
int i = 0;
while (i < pa.size() && i < pb.size() && pa.get(i) == pb.get(i)) i++;
return (pa.size() - i) + (pb.size() - i);
}
// fills 'path' with the nodes from n down to target
private boolean path(TreeNode n, int target, List<TreeNode> path) {
if (n == null) return false;
path.add(n);
if (n.val == target) return true;
if (path(n.left, target, path) || path(n.right, target, path)) return true;
path.remove(path.size() - 1); // not this way, step back
return false;
}
}How long it takes: two walks of the tree, O(n). Extra room: the two paths and the recursion, O(h).
Way 2: the clever way
Do it in one walk, from the bottom up. Each helper reports to its parent how many steps it is down to a target, or "none".
- An empty spot reports none.
- If this node is a target, report 0. If the other target is already below it, the answer is that distance + 1.
- If both sides report a number, this node is the meeting point. The answer is
(left + 1) + (right + 1). - If one side reports a number
x, reportx + 1. Otherwise report none.
Steps travel up until the two paths meet
01 / 09
Find the distance between 7 and 6. Each helper reports up how many steps it is down to a target below it, or "none" if there is no target below.
- distance
- not yet
- looking now
- checking
- seen
- answer
- path
- ignored
class Solution {
private int dist;
public int findDist(TreeNode root, int a, int b) {
if (a == b) return 0;
dist = -1;
down(root, a, b);
return dist;
}
// steps from n down to a target below it, or -1 for none
private int down(TreeNode n, int a, int b) {
if (n == null || dist != -1) return -1;
int l = down(n.left, a, b);
int r = down(n.right, a, b);
if (n.val == a || n.val == b) {
int below = Math.max(l, r); // is the other target under me?
if (below != -1) dist = below + 1;
return 0;
}
if (l != -1 && r != -1) { // the paths meet here
dist = (l + 1) + (r + 1);
return -1;
}
if (l != -1) return l + 1;
if (r != -1) return r + 1;
return -1;
}
}How long it takes: each node is visited at most once, O(n). Extra room: the waiting helpers, O(h).
Watch out for
- Comparing paths by value instead of by node. With unique values it works, but comparing the node objects is safer.
- Missing targets. If
aorbmay not be in the tree, check that both were found before trusting the answer. - Same node twice. The distance is 0.
What interviewers ask next
- With a known lowest common ancestor
L: distance =depth(a) + depth(b) - 2 * depth(L). FindLwith the classic recursive LCA, then two depth searches. - Many questions on the same tree? Precompute depths and use binary lifting, so each question costs
O(log n)afterO(n log n)setup. - All nodes at distance
kfrom a node? Mark each node's parent, then search outward from the node like a graph (LeetCode 863). - In a binary search tree? The meeting point is the first node whose value lies between
aandb, found by walking down from the root.
Remember this
Grown-up words: the shared relative is the lowest common ancestor (LCA), the steps are edges, the reports from the bottom are post order recursion, and -1 is the "none" sentinel.