First Common Ancestor
Design an algorithm to find the first common ancestor of two nodes in a binary tree. Avoid storing additional nodes in the data structure. Note that this is not necessarily a binary search tree.
Solution
The first common ancestor will be the first node for which p
is in the left (or right) subtree, and q
is in the other subtree. For all parent nodes of the common ancestor, p
and q
will be in the same child tree. Thus, we can recurse downwards from the root until we reach a node for which p
is in one child subtree, and q
is in the other child subtree.
First, let’s build a function to identify if a node is contained within a tree. This is fairly straight forward - we can recurse down the tree and return True
if the node is identified.
def child(root, node):
if(root == None):
return False
if(root == node):
return True
left_child = child(root.left, node)
right_child = child(root.right, node)
if(left_child or right_child):
return True
Next, let’s build the main function which will also recurse down the tree, until it encounters a node for which p
is in one subtree, and q
is in the other subtree. If p
and q
are found in the same subtree, we can recursively call the function on that subtree until p
and q
are found in different subtrees.
def first_common_ancestor(root, p, q):
if(root == p) or (root == q):
return root
p_left = child(root.left, p)
q_left = child(root.left, q)
if(p_left != q_left):
return root
elif(p_left):
return first_common_ancestor(root.left, p, q)
elif(not p_left):
return first_common_ancestor(root.right, p, q)