Lowest Common Ancestor of a Binary Tree
Problem statement
Given the root of a binary tree and two of its nodes, p and q, return their lowest common ancestor: the deepest node that has both p and q in its subtree. A node counts as being in its own subtree, so if p is an ancestor of q, the answer is p.
The tree is not a binary search tree, so values say nothing about position. All values are distinct, and both p and q are in the tree. Trees are written in level order, with null for a missing child.
Examples
Example 1
Input: root = [20, 8, 22, 4, 12, null, null, null, null, 10, 14], p = 10, q = 14
Output: 12
Example 2
Input: root = [20, 8, 22, 4, 12, null, null, null, null, 10, 14], p = 8, q = 10
Output: 8
Explanation: 10 is inside 8's subtree, so 8 is its own lowest common ancestor with 10.
Hints
Approach
Do it in one post-order walk. The function returns p or q if it finds one in the subtree, and None otherwise.
- If
nodeis empty, or isporq, returnnode. - Recurse into the left and right subtrees.
- If both sides return a node, then
pis on one side andqon the other, sonodeis the split point: returnnode. - Otherwise return whichever side is not empty (or
None).
Why step 1 can return early: if node is p and q is somewhere below it, p is the answer, and nothing above will find q elsewhere. If q is in another branch, a higher node will see results from both sides. This relies on both nodes being present in the tree.
O(n)Space O(h)from typing import Optional # class TreeNode:# def __init__(self, val=0, left=None, right=None):# self.val = val# self.left = left# self.right = right class Solution: def lowestCommonAncestor(self, root: "TreeNode", p: "TreeNode", q: "TreeNode") -> "TreeNode": if root is None or root is p or root is q: return root left = self.lowestCommonAncestor(root.left, p, q) right = self.lowestCommonAncestor(root.right, p, q) if left and right: # p and q are on different sides return root return left or rightFollow-up questions
- Nodes have a
parentpointer and you are not given the root. Find the LCA usingO(1)extra space. - Find the lowest common ancestor of a whole list of nodes, not just two.
Frequently asked questions
The one-pass version would then return whichever node it found, which is wrong. Count how many of the two targets you actually saw during the walk, and return None unless the count is 2. The path version handles it naturally: if either path is empty, there is no answer.
Yes. In a BST, start at the root and move left while both values are smaller, right while both are larger. The first node where they split, or equal one of them, is the answer, in O(h) time and O(1) space.
Finding the closest shared parent is a common hierarchy question: the common directory of two paths, the lowest shared manager or team in an org tree, or the nearest common commit of two branches (which is what git merge-base finds, though on a graph rather than a tree).