π΅236. Lowest Common Ancestor of a Binary Tree
Medium | Grind 75 | January 17th Tuesday, 2023
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: βThe lowest common ancestor is defined between two nodes p
and q
as the lowest node in T
that has both p
and q
as descendants (where we allow a node to be a descendant of itself).β
Constraints:
The number of nodes in the tree is in the range
[2, 10^5]
.-10^9 <= Node.val <= 10^9
All
Node.val
are unique.p != q
p
andq
will exist in the tree.
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
SOLUTION
Since P
and Q
are known to exist in the tree, the algorithm is guaranteed to find a common ancestor. There are two potential scenarios in which a common ancestor is identified:
When the nodes p and q are found from the left and right subtree, the current node is the common ancestor. This is where
P
andQ
diverges.If only one
P
orQ
is found in a subtree, that node is the LCA for that subtree. For example, ifP
is found in the left subtree, the LCA for the entire left subtree. IfQ
is not found in the right subtree, it is guaranteed to exist under the left subtree, whose LCA isP
.
We use a depth-first search (DFS) approach, recursively iterating over the binary tree and examining both the left and right subtrees. If P
or Q
is found in a subtree, the iteration for that subtree is terminated. The search for the other node continues in the opposite subtree.
# 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':
def dfs(root):
if not root:
return
# return and stop going down the tree from the node
if root == p or root == q:
return root
left, right = None, None
left = dfs(root.left)
right = dfs(root.right)
# current node is where p and q diverge from
if left and right:
return root
# either p or q is the common ancestor or none
return left or right
return dfs(rootQ)
TIME: O(n)
where n is the number of nodes in the binary tree. This is because the helper function 'dfs' visits each node in the binary tree exactly once in the worst case.
SPACE: O(1) since no extra space is being used.
* Written with help from ChatGPT *
Last updated