We use a post-order traversal (bottom-up). If a node is p or q, we return it. If a node receives non-null values from both its left and right children, it must be the LCA.
- Base case: If
rootis None, orrootisporq, returnroot. - Recursively search in the left subtree:
left = lca(root.left, p, q). - Recursively search in the right subtree:
right = lca(root.right, p, q). - If both
leftandrightare not None:- This means
pandqare in different subtrees, sorootis the LCA.
- This means
- If only one is not None, return that non-null value (the found
porq). - If both are None, return None.
- Time Complexity: O(N).
- Space Complexity: O(H).
def lowest_common_ancestor(root, p, q):
if not root 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 right