2Brute2Best
πŸ”₯0

Lowest Common Ancestor of a BST

MediumΒ·LeetCode #235Basic Anchor
LeetCode
30-Second Mental ModelTree DFS β€” LCA on a BST (top-down walk)
Complexity:O(H)β†’O(H)
Key Insight

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.

Core Validity Invariant

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.

01

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.

Input

root, the root of a BST (it has at least 2 nodes), and two different node pointers p and q.

Output

The node that is the lowest common ancestor of p and q.

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

2 is in the left subtree of 6 and 8 is in the right subtree, so 6 is the first node that splits them.

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

4 is below 2. A node counts as its own ancestor, so the answer is 2 itself.

Example 3
Input: root = [2, 1], p = 2, q = 1
Output: 2

1 is the left child of 2, so 2 is the answer.

Constraints
  • β€’ 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.
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck β€” each hint is counted.

  1. 1.

    This tree is a BST. At any node, which side holds the smaller values and which side holds the larger ones?

  2. 2.

    If both targets are smaller than the current node, can either of them be in the right subtree?

  3. 3.

    What does it mean when the two targets are on different sides of the current node?

  4. 4.

    Can the answer be one of the two targets? What would the walk look like then?

  5. 5.

    Do I need to visit both subtrees? How many nodes do I visit in the worst case?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceRecord the path from the root to p and to q; the last node both paths share is the answerO(H)O(H)
OptimalUse the BST order: go left if both are smaller, right if both are larger, else this node is the answerO(H)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • β€œ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.
Ordered tree (BST)+two targets+first node where they split+one path down β†’ O(H)β†’Tree DFS β€” LCA on a BST (top-down walk)

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.

10

Don't make this mistake

Using <= in the split check
βœ— if (p->val <= cur->val && q->val <= cur->val) cur = cur->left;
βœ“ if (p->val < cur->val && q->val < cur->val) cur = cur->left;

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.

Returning the end of p's path (a node can be its own ancestor)
βœ— return pathToP.back();
βœ“ return the last node that both paths share

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.

Pattern confusion: searching both subtrees like LC 236

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.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Tree DFS translate into production architectures and low-level memory mechanics.