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

The Lowest Common Ancestor (LCA) of two nodes in a binary tree is the lowest node that has both nodes as descendants. When parent pointers are available, we can efficiently find the LCA by traversing upward from one node and checking if we encounter the other node's ancestors.

Node Structure

The tree node contains parent pointers for upward traversal ?

TreeNode:
    data: <integer>
    left: <pointer of TreeNode>
    right: <pointer of TreeNode>
    parent: <pointer of TreeNode>

Algorithm

The approach follows these steps ?

  • Create a path from node x to the root by following parent pointers

  • Traverse from node y toward the root, checking if each ancestor appears in x's path

  • Return the first common ancestor found

Example

Let's implement the solution with a complete binary tree example ?

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

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

def make_tree(elements):
    root = TreeNode(elements[0])
    for element in elements[1:]:
        insert(root, element)
    return root

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(x, y):
    # Store path from x to root
    path_to_root = []
    current = x
    
    while current:
        path_to_root.append(current)
        current = current.parent
    
    # Check ancestors of y against x's path
    current = y
    while current:
        if current in path_to_root:
            return current
        current = current.parent
    
    return None

# Create tree: [5, 3, 7, 2, 4, 1, 7, 6, 8, 10]
root = make_tree([5, 3, 7, 2, 4, 1, 7, 6, 8, 10])

# Find LCA of nodes 3 and 7
node_x = search_node(root, 3)
node_y = search_node(root, 7)
lca = find_lca(node_x, node_y)

print(f"LCA of {node_x.data} and {node_y.data} is: {lca.data}")
LCA of 3 and 7 is: 5

How It Works

The algorithm works by creating a path from node x to the root, then traversing from node y upward until finding the first node that exists in x's path. This intersection point is the lowest common ancestor.

Time and Space Complexity

Metric Complexity Explanation
Time O(h) Where h is the height of the tree
Space O(h) For storing the path from x to root

Conclusion

Using parent pointers makes LCA finding efficient with O(h) complexity. The algorithm stores one path and checks intersections, making it optimal for trees with parent references.

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

276 Views

Advertisements