Lowest Common Ancestor in Binary Tree: A practical guide
The lowest common ancestor (LCA) in a binary tree is a fundamental concept in computer science and algorithms. It refers to the deepest node in the tree that has both given nodes as descendants, where a node can be a descendant of itself. Day to day, understanding this concept is crucial for solving various tree-based problems efficiently and is widely used in areas such as network routing, genealogy, and data structure design. This guide explores the problem of finding the LCA in a binary tree, discusses different approaches to solve it, provides code examples, and examines their time and space complexities Surprisingly effective..
Problem Statement
Given a binary tree and two nodes, node1 and node2, the task is to find their lowest common ancestor. As an example, consider the binary tree below:
1
/ \
2 3
/ \ \
4 5 6
If node1 = 4 and node2 = 5, their LCA is 2. Even so, if node1 = 4 and node2 = 6, the LCA is 1.
Approaches to Find LCA in a Binary Tree
1. Recursive Approach
The recursive approach is intuitive and leverages the tree's structure to trace back from the nodes to the root. The algorithm works as follows:
- Base Case: If the current node is
None, returnNone. - Check Current Node: If the current node is one of the target nodes (
node1ornode2), return the current node. - Recursively Search Subtrees: Traverse the left and right subtrees.
- Determine LCA:
- If both subtrees return non-
Nonevalues, the current node is the LCA. - If only one subtree returns a non-
Nonevalue, propagate that value upward (indicating one node is an ancestor of the other).
- If both subtrees return non-
Code Example (Python):
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def find_lca(root, node1, node2):
if not root:
return None
if root == node1 or root == node2:
return root
left_lca = find_lca(root.left, node1, node2)
right_lca = find_lca(root.right, node1, node2)
if left_lca and right_lca:
return root
return left_lca if left_lca else right_lca
Time and Space Complexity:
- Time: O(n), where
nis the number of nodes (worst-case traversal of the entire tree). - Space: O(h), where
his the tree height (due to recursion stack).
2. Iterative Approach Using Stack
An iterative solution avoids recursion by using a stack to simulate traversal. This method tracks the path from the root to each node and then identifies the last common node in both paths But it adds up..
Steps:
- Use a stack to perform depth-first search (DFS) and record the path to each target node.
- Compare the paths to find the last common node.
Code Example (Python):
def find_path(root, target, path):
if not root:
return False
path.append(root)
if root == target:
return True