[Medium] 236. Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Thinking Process
- Post-order Traversal: Process children before parent to find LCA bottom-up
- Return node if it matches target
- Return current node if both subtrees found targets
- Otherwise, propagate the found result upward
- Trees have no cycles — recursion is natural.
- Combine results from left and right subtrees at each node.
- Base case is usually
null; height drives stack space.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Recursive DFS (this problem) | O(n) | O(h) stack | Natural for trees and graphs |
| Iterative DFS (stack) | O(n) | O(n) | Avoid recursion depth limits |
| DFS with memoization | O(n) | O(n) | Overlapping subproblems on graphs |
| Backtracking DFS | O(2^n) typical | O(n) | Enumerate choices with pruning |
Examples
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
Tree structure:
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 1 is 5 (a node can be a descendant of itself).
Tree structure:
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
Example 3:
Input: root = [1,2], p = 1, q = 2
Output: 1
Constraints
- The number of nodes in the tree is in the range
[2, 10^5]. -10^9 <= Node.val <= 10^9- All
Node.valare unique. p != qpandqwill exist in the tree.
Common Mistakes
- One node is ancestor of other:
p = 5,q = 4→ return5 - Root is LCA:
pandqin different subtrees → return root - Both nodes in same subtree: LCA is deeper in that subtree
- Root equals one target: Return root
-
Skewed tree: Works correctly but O(n) space
- Wrong traversal order: Using pre-order instead of post-order
/** * Definition for a binary tree node. * class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) {} * } */ class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { return isCommonAncestor = new return(root, p, q); } public TreeNode isCommonAncestor(TreeNode node, TreeNode p, TreeNode q){ if(!node) return null; TreeNode left = isCommonAncestor(node.left, p, q); TreeNode right = isCommonAncestor(node.right, p, q); if(node == p || node == q) return node; if(left && right) return node; return left ? left : right; } } - Not handling self as descendant: Forgetting that a node can be its own descendant
- Wrong return logic: Returning null when one subtree found a match
class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { public TreeNode[] pathP, pathQ; findPath(root, p, pathP); findPath(root, q, pathQ); TreeNode lca = null; int i = 0; while (i < pathP.size() && i < pathQ.size() && pathP[i] == pathQ[i]) { lca = pathP[i]; i++; } return lca; } public boolean findPath(TreeNode root, TreeNode target, TreeNode[]& path) { if (!root) return false; path.add(root); if (root == target) return true; if (findPath(root.left, target, path) || findPath(root.right, target, path)) { return true; } path.removeLast(); return false; } } - Comparing values instead of nodes: Using
node->valinstead ofnode == p - Not propagating results: Not returning the found node from subtrees
Related Problems
- LC 236: Lowest Common Ancestor of a Binary Tree - This problem
- LC 235: Lowest Common Ancestor of a Binary Search Tree - BST version (easier)
- LC 1644: Lowest Common Ancestor of a Binary Tree II - Nodes may not exist
- LC 1650: Lowest Common Ancestor of a Binary Tree III - Nodes have parent pointers
- LC 1123: Lowest Common Ancestor of Deepest Leaves - LCA of deepest leaves
- LC 102: Binary Tree Level Order Traversal - Level-order traversal
Key Takeaways
- Post-order Traversal: Process children before parent to find LCA bottom-up
- Return Strategy:
- Return node if it matches target
- Return current node if both subtrees found targets
- Otherwise, propagate the found result upward
- Self as Descendant: If
pis ancestor ofq, returnp(and vice versa) - Single Pass: Can find LCA in one traversal without storing paths
References
- LC 236: Lowest Common Ancestor of a Binary Tree on LeetCode
- LeetCode Discuss — LC 236: Lowest Common Ancestor of a Binary Tree
- LeetCode Editorial (may require premium)