Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Solving All Variations of the Lowest Common Ancestor (LCA) Problem in Binary Trees
Mar 25, 2025
452 views
Written by Prashant Basnet
π Welcome to my Signature, a space between logic and curiosity.
Iβm a Software Development Engineer who loves turning ideas into systems that work beautifully.
This space captures the process: the bugs, breakthroughs, and βahaβ moments that keep me building.
Let me walk you through the different variations of the LCA problem and how to solve each one with slight modifications to the core algorithm.
1. Basic LCA Problem
Problem: Find the LCA of two nodes p and q in a binary tree (both nodes guaranteed to exist).
Solution Approach:
var lowestCommonAncestor = function(root, p, q) { function lca(node, p, q) { if (!node) return null; if (node === p || node === q) return node; let left = lca(node.left, p, q); let right = lca(node.right, p, q); if (left && right) return node; // Current node is LCA return left || right; // Propagate whichever side has a found node } return lca(root, p, q); };2. LCA II - Nodes May Not Exist (Leetcode 1644)
Problem: Find LCA of p and q, but return null if either doesn't exist.
Solution Approach:
var lowestCommonAncestor = function(root, p, q) {// Helper to check if node exists in tree
function nodeExists(node, target) { if (!node) return false; if (node === target) return true; return nodeExists(node.left, target) || nodeExists(node.right, target); } // First check if both nodes exist if (!nodeExists(root, p) || !nodeExists(root, q)) return null;// Standard LCA algorithm function lca(node) { if (!node || node === p || node === q) return node; let left = lca(node.left); let right = lca(node.right); if (left && right) return node; return left || right; } return lca(root); };3. LCA IV - Multiple Nodes (Leetcode 1676)
Problem: Find LCA of an array of nodes (all guaranteed to exist).
Solution Approach:
var lowestCommonAncestor = function(root, nodes) { const targets = new Set(nodes.map(n => n.val)); function lca(node) { if (!node) return null; if (targets.has(node.val)) return node; let left = lca(node.left); let right = lca(node.right); if (left && right) return node; return left || right; } return lca(root); };4. LCA III - With Parent Pointers (Leetcode 1650)
Problem: Find LCA when nodes have parent pointers (no root given).
Solution Approach:
(using hash set):
var lowestCommonAncestor = function(p, q) { const visited = new Set(); // Traverse up from p while (p) { visited.add(p); p = p.parent; } // Traverse up from q until we find a visited node while (q) { if (visited.has(q)) return q; q = q.parent; } return null; };Key Insights:
The beauty is that all these variations build on the same fundamental concept - finding the deepest node that contains all target nodes in its descendants.