Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
