Lowest Common Ancestor of a Binary Tree
Lowest Common Ancestor of a Binary Tree is a medium trees & bst problem solved with the lca pattern.
The best approach, optimal (single postorder pass), runs in O(n) time and O(h) space.
Below are 2 approaches in Java, from root-to-node paths up.
Problem
Find the lowest common ancestor of two nodes p and q in a binary tree: the deepest node that has both of them as descendants (a node counts as a descendant of itself).
Examples
Example 1
- Input
root = [3, 5, 1, 6, 2, 0, 8, null, null, 7, 4], p = 5, q = 1- Output
3
Example 2
- Input
same tree, p = 5, q = 4- Output
5- Why
- A node can be its own ancestor.
Constraints
- The tree has
2to10^5nodes, unique values. - p and q both exist in the tree.
Animated walkthrough
A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.
Concepts first, then the problem and every approach, step by step.
Space to play or pause · ← → to jump a step · click or drag the bar to seek
Solutions
Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.
| Approach | Time | Space |
|---|---|---|
| Root-to-node paths | O(n) | O(n) |
| Optimal (single postorder pass) | O(n) | O(h) |
1Root-to-node paths
O(n)O(n)Record the path from the root to p and the path to q, then walk both until they differ. The last shared node is the LCA.
- path(root, target, list) with backtracking.
- Compare paths index by index.
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
List<TreeNode> a = new ArrayList<>(), b = new ArrayList<>();
path(root, p, a);
path(root, q, b);
TreeNode lca = null;
for (int i = 0; i < Math.min(a.size(), b.size()) && a.get(i) == b.get(i); i++) lca = a.get(i);
return lca;
}
private boolean path(TreeNode n, TreeNode target, List<TreeNode> out) {
if (n == null) return false;
out.add(n);
if (n == target || path(n.left, target, out) || path(n.right, target, out)) return true;
out.remove(out.size() - 1);
return false;
}
}2Optimal (single postorder pass)
O(n)O(h)Return p or q when you hit them, null when a subtree has neither. If both left and right return non-null, this node splits them, so it is the LCA. Otherwise pass up whichever side found something.
- If root is null, p or q, return root.
- left = lca(left), right = lca(right).
- If both non-null, return root; else return the non-null one.
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) return root;
return left != null ? left : right;
}
}Edge cases to test
- One node is the ancestor of the other
- p and q in different subtrees of the root
Hints
Hint 1
If p is found in one subtree and q in the other, the current node is the answer.
FAQ
What is the best time complexity for Lowest Common Ancestor of a Binary Tree?
Optimal (single postorder pass) runs in O(n) time and O(h) extra space.
Which pattern does Lowest Common Ancestor of a Binary Tree use?
It is a trees & bst problem that uses the lca pattern. Other problems with the same pattern: Lowest Common Ancestor of a Binary Search Tree.
Is there a brute force solution for Lowest Common Ancestor of a Binary Tree?
Yes. Root-to-node paths takes O(n) time and O(n) space. Record the path from the root to p and the path to q, then walk both until they differ.
Which edge cases should I test for Lowest Common Ancestor of a Binary Tree?
One node is the ancestor of the other; p and q in different subtrees of the root.