Description
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).”
Examples:
Example 1:
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.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Example 3:
Input: root = [1,2], p = 1, q = 2
Output: 1
Solution in Python
Approach:
- If the current node is
None
, returnNone
because we’ve reached the end of a path. - If the current node is equal to
p
orq
, return the current node because one of the targets has been found. - Recursively search for
p
andq
in both the left and right subtrees. - If
p
andq
are found in different subtrees, the current node is their lowest common ancestor. - If both are found in the left or both in the right subtree, the LCA is in that subtree.
Python
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# Base case: if root is None, or root is either p or q, return root
if root is None or root == p or root == q:
return root
# Recursively search for p and q in the left and right subtrees
left = self.lowestCommonAncestor(root.left, p, q) # Search in the left subtree
right = self.lowestCommonAncestor(root.right, p, q) # Search in the right subtree
# If both left and right are non-null, p and q are in different subtrees,
# so the current root is their lowest common ancestor
if left and right:
return root
# If only one side (either left or right) has returned a node,
# it means both p and q are in that subtree.
# So return the non-null node (either left or right).
return left if left else right
Explanation:
- Base Case:
- If the current node (
root
) isNone
, that means we’ve reached a leaf node without findingp
orq
. We returnNone
. - If
root
is eitherp
orq
, returnroot
because one of the targets has been found.
- If the current node (
- Recursive Calls:
- We search both the left and right subtrees by making recursive calls to
lowestCommonAncestor()
forroot.left
androot.right
.
- We search both the left and right subtrees by making recursive calls to
- Check if Current Node is the LCA:
- If both recursive calls return non-
None
values (i.e., bothleft
andright
are non-null), it meansp
was found in one subtree, andq
was found in the other. Therefore, the current node (root
) is their LCA.
- If both recursive calls return non-
- Return Result:
- If only one of
left
orright
is non-null, it means bothp
andq
are in the same subtree. In this case, return the non-null value (left
orright
).
- If only one of
Solution in Javascript
JavaScript
var lowestCommonAncestor = function(root, p, q) {
// Base case: if root is null, or root is either p or q, return root
if (root === null || root === p || root === q) {
return root;
}
// Recur for the left and right subtrees
const left = lowestCommonAncestor(root.left, p, q); // Search in left subtree
const right = lowestCommonAncestor(root.right, p, q); // Search in right subtree
// If both left and right are non-null, this means p and q are in different subtrees,
// so the current node is the lowest common ancestor
if (left !== null && right !== null) {
return root;
}
// Otherwise, return the non-null value (if either left or right is non-null)
return left !== null ? left : right;
};
Solution in Java
Java
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// Base case: if root is null, or root is either p or q, return root
if (root == null || root == p || root == q) {
return root;
}
// Recur for the left and right subtrees
TreeNode left = lowestCommonAncestor(root.left, p, q); // Search in left subtree
TreeNode right = lowestCommonAncestor(root.right, p, q); // Search in right subtree
// If both left and right are non-null, p and q are in different subtrees,
// so the current node is the lowest common ancestor
if (left != null && right != null) {
return root;
}
// Otherwise, return the non-null value (either left or right)
return (left != null) ? left : right;
}
}
Solution in C++
C++
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// Base case: if root is null or root is either p or q, return root
if (root == nullptr || root == p || root == q) {
return root;
}
// Recursively search in the left subtree
TreeNode* left = lowestCommonAncestor(root->left, p, q);
// Recursively search in the right subtree
TreeNode* right = lowestCommonAncestor(root->right, p, q);
// If both left and right are non-null, p and q are in different subtrees,
// so the current root is their lowest common ancestor
if (left != nullptr && right != nullptr) {
return root;
}
// If only one of left or right is non-null, return that node
// This means both p and q are in the same subtree
return left != nullptr ? left : right;
}
};