LCA without parent pointers
Given the root of a binary tree, and 2 nodes, determine the LCA. Note: The nodes do not have parent pointers.
Solution
- Use a recursive solution
- If both nodes are present in the left subtree, recurse towards the left
- If both are present in the right subtree, recurse towards the right
- If one is in the left and other is on the right, then we have found out LCA.
- To prevent revisiting some of the nodes, return the lca and num nodes found in each subtree
Code
def find_lca(root, node1, node2)
lca, num_nodes = lca_helper(root, node1, node2)
return lca
end
def lca_helper(root, node1, node2)
return 0, nil if node1.nil?
return 0, nil if node2.nil?
# Test if lca is in the left subtree
left_lca, left_num = lca_helper(root.left, node1, node2)
return left_lca if left_num == 2
# Test if lca is in the right subtree
right_lca, right_num = lca_helper(root.right, node1, node2)
return right_lca if right_num == 2
# When each node is on either side of the current root
num = left_lca + right_lca
# When one node is in the parent chain of the other
num += 1 if root == node1 || root == node2
# If LCA is found return it, else return nil to continue looking for LCA
lca = num == 2 ? root : nil
return num, lca
end
Complexity
- Time: O(n), since we are doing a form of pre-order traversal.
- Space: O(h), since we are storing temporary nodes while recursing along the height of the tree.