Lowest Common Ancestor of a Binary Search Tree — Coding Interview Walkthrough
You’re given a BST and two nodes. Find their lowest common ancestor. Most candidates reach for the generic binary tree LCA algorithm, which works but completely ignores the BST property. Interviewers notice. The real test here is whether you can exploit the ordering constraint to turn an O(n) traversal into an O(h) walk down the tree, and whether you can articulate why the split point is the answer.
The Problem
Given a binary search tree and two nodes p and q, find their lowest common ancestor (LCA). The LCA is defined as the deepest node that has both p and q as descendants (a node can be a descendant of itself).
Example
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Output: 6
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Output: 2
Node 2 is the ancestor of both itself and node 4.
Already comfortable with the solution? Practice it in a mock interview →
What Interviewers Are Actually Testing
| Skill | What Interviewers Observe |
|---|---|
| BST property exploitation | Do you use val comparisons instead of generic tree traversal? |
| LCA intuition | Do you understand what “split point” means? |
| Iterative vs. recursive | Can you write both and explain the space difference? |
| LCA generalization | Do you know this differs from LCA of a general binary tree? |
Step 1: Clarifying Questions
- Is this a BST or a general binary tree? Critical. BST ordering enables a simple comparison-based approach that doesn’t work on general trees.
- Are
pandqguaranteed to exist in the tree? Assume yes per problem constraints. - Can a node be its own ancestor? Yes. The LCA of
2and4in the example is2itself.
Step 2: The Naive Idea
Treat it like a general binary tree and do a standard LCA via DFS — checking if each subtree contains p or q. Works, but ignores the BST property. O(n) time. We can do better.
Step 3: The Key Insight
In a BST, the LCA is the first node where p and q “split.” If both p.val and q.val are less than node.val, the LCA is in the left subtree. If both are greater, it’s in the right subtree. The moment they’re on opposite sides (or one equals node.val), you’ve found the LCA.
This reduces the search to O(h) — tree height — by exploiting BST structure.
Step 4: Optimal Strategy
- Start at the root.
- If both
p.valandq.val<node.val: go left. - If both
p.valandq.val>node.val: go right. - Otherwise: current node is the LCA. Return it.
Python Implementation
Recursive:
def lowestCommonAncestor(root, p, q):
if p.val < root.val and q.val < root.val:
return lowestCommonAncestor(root.left, p, q)
if p.val > root.val and q.val > root.val:
return lowestCommonAncestor(root.right, p, q)
return root # Split point found
Iterative (O(1) space):
def lowestCommonAncestor(root, p, q):
node = root
while node:
if p.val < node.val and q.val < node.val:
node = node.left
elif p.val > node.val and q.val > node.val:
node = node.right
else:
return node
Time & Space Complexity
| Approach | Time | Space |
|---|---|---|
| Recursive | O(h) | O(h) call stack |
| Iterative | O(h) | O(1) |
For a balanced BST, h = O(log n). For a skewed BST, h = O(n).
Common Interview Mistakes
-
Using the general binary tree LCA approach. It works but ignores the BST structure. Interviewers view this as a missed optimization.
-
Not handling the case where
porqequals the current node. Theelsebranch handles this correctly since ifp.val == root.val, neither condition is true. -
Not knowing the difference between LCA of BST (#235) and LCA of binary tree (#236). The BST version is O(h); the general version is O(n). Being able to state this distinction shows depth.
-
Forgetting that the iterative version is O(1) space. Always mention this as an advantage over the recursive version.
What a Strong Candidate Sounds Like
“Since this is a BST, I can exploit the ordering property. At each node, if both target values are less than the current value, the LCA must be in the left subtree. If both are greater, go right. The first node where they split — or one equals the node — is the LCA. This is O(h) time and O(1) space with the iterative version.”
Example Interview Dialogue
Interviewer: How would your approach change for a general binary tree?
Candidate: For a general tree I can’t use value comparisons to decide direction. I’d do a full DFS: at each node, recursively check if the left subtree contains p, the right contains q, or vice versa. The node where both subtrees return a match (or the node itself is one of the targets) is the LCA. That’s O(n) time instead of O(h).
Interviewer: What if the BST is highly skewed?
Candidate: Then h = O(n) and we lose the logarithmic advantage. The algorithm still works correctly, but performance degrades to linear. If we needed guaranteed O(log n), we’d need a self-balancing BST like a red-black tree or AVL tree.
Related Problems to Practice
- Lowest Common Ancestor of a Binary Tree — General tree version, O(n) required.
- Validate Binary Search Tree — Tests the same BST property understanding.
- Invert Binary Tree — Tree recursion fundamentals.
Practice This in a Mock Interview
The split-point insight is easy to understand when reading about it. Articulating it fluently while an interviewer watches — that’s the hard part. Practice explaining why the split point is the answer, not just what code to write.
Start a mock interview for Lowest Common Ancestor of a BST on Intervu.
Further reading:
- How to Prepare for a Coding Interview in 2026, the complete roadmap
- Why LeetCode alone isn’t enough, and what to practice instead
- Practice any LeetCode problem as a live mock interview
- The Grind 75 Pathway, a structured study plan with AI practice links
- Browse all walkthroughs on GitHub