Finding the Lowest Common Ancestor in Binary Trees

Core Approach

1. Base Cases:

  • If the current node is null, return null
  • If the current node matches either target, return the current node (a node is its own ancestor)

2. Recursive Search:

  • Recursively search the left subtree, storing the result
  • Recursively search the right subtree, storing the result

3. Result Analysis:

  • If both left and right results are non-null → current node is the lowest common ancestor
  • If only the left result is non-null → the ancestor is in the left subtree
  • If only the right result is non-null → the ancestor is in the right subtree

Why Return When Finding a Target?

The core principle is that recursion propagates found markers upward.

The function's purpose must be clear: findCommonAncestor(currentNode, target1, target2)

If the subtree rooted at currentNode contains either target, return the found node. If neither target is present, return null.

Scenario 1: Current Node is a Target

When the current node matches one target, it guarantees that subtree contains that target. According to the function's responsibility, it returns itself, signaling upward: "I found the target."

Scenario 2: Current Node is the Other Target

Similarly, the function returns itself to indicate: "I found the other target."

Implementation Details

1. Node Structure: Standard binary tree node with value, left child, and right child references.

2. Recursive Logic:

  • Begin traversal from the root node
  • If both targets are found in different subtrees, the current node is their LCA
  • If both targets are found in the same subtree, continue propagating that result upward

3. Time Complexity: O(n) - In the worst case, we traverse the entire tree once

4. Space Complexity: O(n) - Due to the recursion stack in the worst case (skewed tree)

Python Implementation

class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left_child = None
        self.right_child = None

csSolution:
    def find_common_ancestor(self, current_node, target1, target2):
        # Base cases: null node or found a target
        if current_node is None or current_node == target1 or current_node == target2:
            return current_node
        
        # Search left subtree
        left_result = self.find_common_ancestor(current_node.left_child, target1, target2)
        # Search right subtree
        right_result = self.find_common_ancestor(current_node.right_child, target1, target2)
        
        # Case 1: Targets found in different subtrees
        if left_result and right_result:
            return current_node
        # Case 2: Only left subtree contains targets
        elif left_result:
            return left_result
        # Case 3: Only right subtree contains targets
        else:
            return right_result

Tags: binary tree lowest common ancestor Tree Algorithms Recursion Data Structures

Posted on Mon, 11 May 2026 08:08:11 +0000 by enoyhs