LCA is the deepest node that is an ancestor of both given nodes. The core insight:
If left subtree has one target and right subtree has the other → current node is the LCA.
Focus on recognizing:
“Common ancestor” + “Two nodes in tree” + “Distance between nodes” = LCA
Pattern Table
| Pattern | Typical Questions | Trigger |
|---|---|---|
| Basic LCA | Find common ancestor | Left has one, right has the other |
| LCA with Parent Pointer | Parent references available | Climb up to match |
| Distance Between Nodes | Number of edges between nodes | depth(a) + depth(b) - 2 * depth(lca) |
Mental Trigger
DFS returns target node or null → If both left and right return non-null, current is LCA.
1. Generic Java LCA Template (Base)
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q)
return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null)
return root;
return left != null ? left : right;
}def lowest_common_ancestor(root, p, q):
if root is None or root == p or root == q:
return root
left = lowest_common_ancestor(root.left, p, q)
right = lowest_common_ancestor(root.right, p, q)
if left and right:
return root
return left if left else rightTreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr || root == p || root == q)
return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left != nullptr && right != nullptr)
return root;
return left != nullptr ? left : right;
}function lowestCommonAncestor(root, p, q) {
if (root === null || root === p || root === q)
return root;
const left = lowestCommonAncestor(root.left, p, q);
const right = lowestCommonAncestor(root.right, p, q);
if (left !== null && right !== null)
return root;
return left !== null ? left : right;
}Everything else in LCA is just a modification of this template.
Pattern 1: LCA of BST
The split point — targets on different sides — IS the ancestor. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Lowest Common Ancestor In A BST
Find the LCA of two nodes in a BST.
Walk from the root: if both targets are smaller go left, both larger go right; the first node where they split (one on each side, or the node equals one target) is the LCA. BST ordering does the work in O(h) with no parent pointers.
1
while root:
2
both < root → go left
3
both > root → go right
4
else → SPLIT = answer
Java Code
public TreeNode lowestCommonAncestorBST(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestorBST(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestorBST(root.right, p, q);
return root;
}def lowest_common_ancestor_bst(root, p, q):
if root.val > p.val and root.val > q.val:
return lowest_common_ancestor_bst(root.left, p, q)
if root.val < p.val and root.val < q.val:
return lowest_common_ancestor_bst(root.right, p, q)
return rootTreeNode* lowestCommonAncestorBST(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root->val > p->val && root->val > q->val)
return lowestCommonAncestorBST(root->left, p, q);
if (root->val < p->val && root->val < q->val)
return lowestCommonAncestorBST(root->right, p, q);
return root;
}function lowestCommonAncestorBST(root, p, q) {
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestorBST(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestorBST(root.right, p, q);
return root;
}What Changed from the Base Template?
BST property eliminates branches
Base:
// check both subtrees recursively
Changed:
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestorBST(root.left, p, q);
because in BST, if both nodes are smaller than root, LCA must be in the left subtree.
LCA in BST = Compare values + Go left if both smaller, right if both larger.
Pattern 2: Distance Between Two Nodes
d(p) + d(q) − 2·d(LCA): shared ancestry cancels out. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Distance Between Two Nodes
Compute the number of edges between two nodes using their lowest common ancestor.
Walk down from the root to find the LCA (the split node where the two targets diverge), then distance = d(p,LCA) + d(q,LCA), equivalently depth(p)+depth(q)−2·depth(LCA). Works for plain binary trees once LCA is found.
1
LCA = split node of (4, 7)
2
d(n, LCA) via BST walk
3
answer = d(4,L) + d(7,L)
Java Code
public int distance(TreeNode root, TreeNode p, TreeNode q) {
TreeNode lca = lowestCommonAncestor(root, p, q);
return depth(root, lca) + depth(root, p) + depth(root, q) - 2 * depth(root, lca);
}
// ponytail: distance = depth(p) + depth(q) - 2 * depth(lca)def distance(root, p, q):
lca = lowest_common_ancestor(root, p, q)
return depth(root, lca) + depth(root, p) + depth(root, q) - 2 * depth(root, lca)int distance(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* lca = lowestCommonAncestor(root, p, q);
return depth(root, lca) + depth(root, p) + depth(root, q) - 2 * depth(root, lca);
}function distance(root, p, q) {
const lca = lowestCommonAncestor(root, p, q);
return depth(root, lca) + depth(root, p) + depth(root, q) - 2 * depth(root, lca);
}What Changed from the Base Template?
Distance formula
Added:
int dist = depth(root, p) + depth(root, q) - 2 * depth(root, lca);
because the path from p to q goes up from p to LCA then down to q.
Distance = depth(p) + depth(q) - 2 * depth(lca).
LCA Pattern Evolution
Basic LCA (DFS + left/right return checks)
↓
LCA in BST
(+ value comparison + single branch descent)
↓
Distance Between Nodes
(+ LCA + depth formula)
Common Mistakes
Not handling the case where one node is ancestor of the other.
Basic LCA handles this: if root == p, return root before recursing.
Confusing LCA with common ancestor in BST.
BST LCA is simpler — compare values, no need for full DFS.
Using O(n) depth calculation repeatedly.
For single query, O(n) is fine. For multiple queries, precompute depths or use binary lifting.
Recognition Cheat Sheet
| If you see… | Think… |
|---|---|
| Common ancestor of two nodes | LCA via DFS |
| BST + common ancestor | BST LCA (value compare) |
| Distance between nodes | LCA + depth formula |
| Multiple LCA queries | Binary lifting (preprocess) |
Premium Content
Unlock Lowest Common Ancestor and all premium lessons with a subscription.
From ₹199.99/year — See plans