Lowest Common Ancestor of a Binary Tree III
Medium · Two Pointers · Explanation and code example
Iteration - II
How it works
This approach is similar to finding the intersection of two linked lists. We use two pointers starting at p and q. When a pointer reaches the root (null), we redirect it to the other starting node. After at most two passes, both pointers will have traveled the same total distance and will meet at the LCA.
Steps
- Initialize two pointers
ptr1 = pandptr2 = q. - While
ptr1 != ptr2:- Move
ptr1to its parent, or toqif it reachesnull. - Move
ptr2to its parent, or topif it reachesnull.
- Move
- Return
ptr1(orptr2) as the LCA.
Complexity
- Time complexity:
O(n) - Space complexity:
O(1)
Things to watch for
Forgetting to Handle Equal Depths
When using the height-based iteration approach, a common mistake is assuming p and q are always at different depths. If both nodes are at the same level, no adjustment is needed before the lockstep traversal. Failing to handle this case correctly can lead to infinite loops or null pointer exceptions.
Using Value Comparison Instead of Reference Comparison
Since nodes can have duplicate values, comparing p.val == q.val is incorrect. You must compare node references (p == q or p is q) to determine when the two pointers have met at the same node. Using value comparison will produce wrong results when different nodes have the same value.
Not Recognizing the Linked List Intersection Pattern
This problem is essentially finding the intersection of two linked lists (the paths from p and q to the root). The elegant two-pointer solution works because both pointers travel the same total distance before meeting. Missing this insight leads to more complex solutions using extra space for hash sets when O(1) space is achievable.
Python code example
"""
# Definition for a Node.
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
self.parent = None
"""
class Solution:
def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
ptr1, ptr2 = p, q
while ptr1 != ptr2:
ptr1 = ptr1.parent if ptr1 else q
ptr2 = ptr2.parent if ptr2 else p
return ptr1
C++ code example
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* parent;
};
*/
class Solution {
public:
Node* lowestCommonAncestor(Node* p, Node* q) {
Node* ptr1 = p;
Node* ptr2 = q;
while (ptr1 != ptr2) {
ptr1 = ptr1 ? ptr1->parent : q;
ptr2 = ptr2 ? ptr2->parent : p;
}
return ptr1;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.