Program to find out the lowest common ancestor of a binary tree using Python

The Lowest Common Ancestor (LCA) of two nodes in a binary tree is the deepest node that has both nodes as descendants. A node can be considered a descendant of itself. This problem is commonly solved using recursive traversal.

So, if the input is like:

5 3 7 2 4 1 6 LCA of 2 and 4

For x = 2 and y = 4, the output will be 3 because node 3 is the lowest common ancestor of both nodes 2 and 4.

Algorithm

The solution uses a depth-first search (DFS) approach:

  • If the current node is null, return null
  • If the current node matches either target node, return the node
  • Recursively search left and right subtrees
  • If both subtrees return non-null values, current node is the LCA
  • Otherwise, return whichever subtree found a target node

Implementation

class TreeNode:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def insert(temp, data):
    queue = []
    queue.append(temp)
    while queue:
        temp = queue.pop(0)
        if not temp.left:
            if data is not None:
                temp.left = TreeNode(data)
            else:
                temp.left = TreeNode(0)
            break
        else:
            queue.append(temp.left)
        if not temp.right:
            if data is not None:
                temp.right = TreeNode(data)
            else:
                temp.right = TreeNode(0)
            break
        else:
            queue.append(temp.right)

def make_tree(elements):
    if not elements:
        return None
    tree = TreeNode(elements[0])
    for element in elements[1:]:
        insert(tree, element)
    return tree

def search_node(root, element):
    if root is None:
        return None
    if root.data == element:
        return root
    res1 = search_node(root.left, element)
    if res1:
        return res1
    res2 = search_node(root.right, element)
    return res2

def find_lca(root, x, y):
    def dfs(node):
        if not node:
            return None
        
        # If current node is one of the target nodes
        if node == x or node == y:
            return node
        
        # Search in left and right subtrees
        left = dfs(node.left)
        right = dfs(node.right)
        
        # If both subtrees contain target nodes, current node is LCA
        if left and right:
            return node
        
        # Return whichever subtree contains a target node
        return left or right
    
    return dfs(root)

# Example usage
root = make_tree([5, 3, 7, 2, 4, 1, 6])
node_x = search_node(root, 2)
node_y = search_node(root, 4)
lca = find_lca(root, node_x, node_y)
print(f"LCA of {node_x.data} and {node_y.data} is: {lca.data}")

The output of the above code is:

LCA of 2 and 4 is: 3

How It Works

The algorithm works by performing a post-order traversal of the binary tree. When it finds one of the target nodes, it returns that node up the recursion stack. If a node receives non-null values from both its left and right subtrees, it means both target nodes exist in different subtrees, making the current node their LCA.

Time Complexity

The time complexity is O(n) where n is the number of nodes in the tree, as we might visit all nodes in the worst case. The space complexity is O(h) where h is the height of the tree due to the recursion stack.

Conclusion

The LCA problem is efficiently solved using recursive DFS traversal. The key insight is that the LCA is the first node that has both target nodes in different subtrees during the bottom-up traversal.

Updated on: 2026-03-25T21:06:05+05:30

231 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements