Skip to content
AI360Xpert
Beta
Difficulty: MediumTrees

Lowest Common Ancestor of a Binary Search Tree

Problem in Plain English

Given a binary search tree with two nodes p and q that both exist in it, return the deepest node that is an ancestor of both. A node counts as its own descendant.

Problem Statement

Given the root of a binary search tree and two nodes p and q, return their lowest common ancestor.

The lowest common ancestor is the deepest node that has both p and q as descendants, where a node counts as a descendant of itself.

Both nodes are guaranteed to exist in the tree, they hold distinct values, and every value in the tree is unique.

Constraints

  • 2 <= number of nodes <= 10^5
  • -10^9 <= Node.val <= 10^9
  • All node values are unique
  • p != q and both p and q exist in the tree

Examples

Example 1

Input
root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output
6

Basic split: the paths are [6,2] and [6,8]. Their last common node is 6; neither child subtree contains both targets. The output shows the returned node's value.

Example 2

Input
root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output
2

Ancestor case: the paths are [6,2] and [6,2,4]. Node 2 counts as its own descendant, so it is the deepest common ancestor. Strict comparisons must stop when the current node equals a target.

Example 3

Input
root = [2,1], p = 2, q = 1
Output
2

Minimum-size edge case: the tree has only two nodes. The root 2 is both a target and the parent of 1, so return the existing root node.

Example 4

Input
root = [6,2,8,0,4,7,9,null,null,3,5], p = 5, q = 3
Output
4

Tricky deeper split with reversed target order: both targets are below 6 on its left, then above 2 on its right. At 4, 5 is larger and 3 is smaller. Return 4; the algorithm must work without assuming p has the smaller value.

Intuition

A common ancestor lies on both root-to-target paths; the lowest one is the last node before those paths diverge. In Example 1, the paths to 2 and 8 share only 6. A BST adds a shortcut: if both target values are smaller than the current value, their shared path continues left; if both are larger, it continues right. At a split, or when the current node is a target, we have reached the answer. Return that original node reference, rather than its value or a new node.

Approaches

Root To Node Paths

Solution Details

Reveal Root To Node Paths: intuition, complexity, and code

Hints

Hint 1
Values left of a node are smaller and values right of it are larger, so both targets on one side means the answer waits down that side.
Hint 2
When one target is smaller and the other is larger, the current node is where their routes split.
Hint 3
A target equal to the current node also ends the walk, since a node is its own ancestor.

Edge Cases

  • With only two nodes, the root is the LCA of the two targets, including its own descendant relationship.
  • One target is an ancestor of the other; stop at that target rather than moving past equality.
  • Targets lie on opposite sides of the root; return the root without searching its children.
  • Both targets initially lie on the same side, but split much deeper, as in Example 4. Target order can be reversed.
  • A 100,000-node skewed BST has linear height; explicit DFS frames and the iterative BST walk both avoid recursive call-stack limits.
  • Negative and extreme values follow the same ordering rules; direct comparisons need no subtraction and cannot overflow.

Common Mistakes and Interview Tips

  • Using <= or >= for same-side tests moves past a target that is itself the LCA; use strict comparisons.
  • Returning curr.val or constructing a new node loses the required original node reference; the example output only displays its value.
  • Assuming p is smaller than q breaks reversed target pairs. Test both targets independently against the current value.
  • Calling a BST walk O(log n) unconditionally ignores skewed trees. State O(h), with the balance assumptions separately.
  • Claiming that each step discards half the nodes assumes a balanced tree; BST ordering guarantees a valid subtree choice, not its size.
  • In the general path search, omitting exit frames leaves failed branches in the path; scheduling right before left on a LIFO stack makes the intended left-first order.
  • Recursive general DFS may overflow on the permitted 100,000-node chain; use explicit frames as shown.
  • The guarantee that both original target nodes exist is essential. If targets could be absent, the split test alone would not prove an ancestor exists; validate membership under that different contract.

Key Takeaway

The LCA is where two root-to-target routes stop sharing a prefix. A general tree needs path discovery and backtracking; BST ordering identifies the shared route using two value comparisons per node. Preserve the invariant that the chosen subtree contains both targets, then stop when no proper descendant can do so.