Problem of The Day: Lowest Common Ancestor of a Binary Tree
Problem Statement
see link.
Intuition
The problem involves finding the lowest common ancestor (LCA) of two nodes in a binary tree. The lowest common ancestor is the deepest node in the tree that has both nodes as descendants. My intuition is to use a recursive approach to traverse the tree and identify the LCA.
Approach
I’ll recursively traverse the binary tree starting from the root. During the traversal, I’ll check if the current node is one of the given nodes (p
or q
). If it is, I’ll set the found
flag to true. I’ll also recursively search for the nodes in the left and right subtrees.
To identify the LCA, I’ll consider three cases:
- If both nodes are found in the left and right subtrees, or one node is found in the current subtree and the other in either the left or right subtree, then the current node is the LCA.
- If only one node is found in the current subtree, I’ll return that node as a potential LCA.
- If none of the above conditions is met, I’ll return None.
Complexity
-
Time complexity: O(n), where n is the number of nodes in the binary tree. In the worst case, I may need to traverse all nodes.
-
Space complexity: O(h), where h is the height of the binary tree. This is due to the recursion stack during the traversal.
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return None
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
found = root is p or root is q
if (left and found) or (right and found) or (left and right):
return root
return left or right or found
Editorial Solution
class Solution:
def __init__(self):
# Variable to store LCA node.
self.ans = None
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
def recurse_tree(current_node):
# If reached the end of a branch, return False.
if not current_node:
return False
# Left Recursion
left = recurse_tree(current_node.left)
# Right Recursion
right = recurse_tree(current_node.right)
# If the current node is one of p or q
mid = current_node == p or current_node == q
# If any two of the three flags left, right or mid become True.
if mid + left + right >= 2:
self.ans = current_node
# Return True if either of the three bool values is True.
return mid or left or right
# Traverse the tree
recurse_tree(root)
return self.ans