Lowest Common Ancestor of a BST
Start at the root. If both p and q are smaller than the node, both live in its left subtree, so move left. If both are larger, move right. Otherwise the two targets are on different sides (or one of them is this node), so this node is the answer.
A node is the answer when p and q are not both smaller and not both larger than it. Then one target is on each side, or the node is one of them.
Problem
You are given the root of a binary search tree (BST) and two nodes p and q that are both in the tree.
Find their lowest common ancestor (LCA). This is the lowest node that has both p and q below it. A node counts as its own ancestor, so if p is above q, the answer is p.
Return the node itself, not its value.
root, the root of a BST (it has at least 2 nodes), and two different node pointers p and q.
The node that is the lowest common ancestor of p and q.
2 is in the left subtree of 6 and 8 is in the right subtree, so 6 is the first node that splits them.
4 is below 2. A node counts as its own ancestor, so the answer is 2 itself.
1 is the left child of 2, so 2 is the answer.
- β’ The number of nodes in the tree is in the range [2, 10^5].
- β’ β10^9 β€ Node.val β€ 10^9
- β’ All Node.val are unique.
- β’ p β q
- β’ p and q will exist in the BST.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck β each hint is counted.
- 1.
This tree is a BST. At any node, which side holds the smaller values and which side holds the larger ones?
- 2.
If both targets are smaller than the current node, can either of them be in the right subtree?
- 3.
What does it mean when the two targets are on different sides of the current node?
- 4.
Can the answer be one of the two targets? What would the walk look like then?
- 5.
Do I need to visit both subtrees? How many nodes do I visit in the worst case?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Record the path from the root to p and to q; the last node both paths share is the answer | O(H) | O(H) |
| Optimal | Use the BST order: go left if both are smaller, right if both are larger, else this node is the answer | O(H) | O(1) |
Why does this belong to this pattern?
- βlowest common ancestorβWe want the first node that splits the two targets. Walk down from the top. Do not check the whole tree.
- βbinary search treeβValues are ordered, so one comparison rules out a whole side for each target.
- βa node can be its own ancestorβIf the walk stops on one of the targets, that target is the answer. The stop rule must handle equal values.
The BST order tells us which side each target is on, so every step drops one whole subtree. This is the anchor of the LCA sub-pattern: compare both targets with the node, then go left, go right, or stop. Only one comparison per level is needed, not a search of both sides. LC 236 has no order, so it has to check both sides, which is the next question.
Don't make this mistake
Equal values need the strict test. On the tree above with p = 2 and q = 0: at 6 both are smaller, so we go to 2. At 2, p equals the node, so <= says both are smaller and the walk goes left to 0, which returns 0. The right answer is 2, because 2 is an ancestor of 0 and counts as its own ancestor.
Take p = 4 and q = 2. The path to 4 is 6, 2, 4, and the path to 2 is 6, 2. The end of p's path is 4. But 2 is an ancestor of 4, and a node counts as its own ancestor, so the answer is 2. Only the shared part of the two paths can decide the answer.
The BST order makes one side impossible, so searching both subtrees is wasted work. The answer is still correct, but on the tree above with p = 3 and q = 5, a full search visits all 9 nodes. The BST walk visits only 3 of them: 6, 2 and 4.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Tree DFS translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.