Lowest Common Ancestor LCA in a Binary Tree - Nodes May Not Exist in Tree# Problem# Given the root of a binary tree, return the lowest common ancestor (LCA) of two given nodes, p and q. If either node p or q does not exist in the tree, return null. All values of the nodes in the tree are unique.
Lowest Common Ancestor Definition
Problems related to it - Lowest Common Ancestor Definition
Examples# Example 1:
1
2
3
4
5
6
7
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2_ 0 8
/ \
7 4
1
2
3
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:
1
2
3
4
5
6
7
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2_ 0 8
/ \
7 4
1
2
3
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 10
Output: null
Explanation: Node 10 does not exist in the tree, so return null.
Follow up# Can you find the LCA traversing the tree, without checking nodes existence?
Solution# Method 1 - Two Pass - Check Nodes Existence# Algorithm# Check if node p and q exists in Tree. If either of them don’t exist, return null. Else return the LCA we used to to solve - Lowest Common Ancestor of a Binary Tree#Method 2 - Using Post-order Traversal 🏆 . Code#
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) {
boolean l = check(root, p);
boolean k = check(root, q);
if (! l || ! k) {
return null ;
}
return dfs(root, p, q);
}
private boolean check (TreeNode root, TreeNode p) {
if (root == null ) {
return false ;
}
if (root == p) {
return true ;
}
return check(root.left , p) || check(root.right , p);
}
public TreeNode dfs (TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode left = dfs(root.left , p, q);
TreeNode right = dfs(root.right , p, q);
if (left != null && right != null ) {
return root;
}
return left != null ? left : right;
}
Method 2 - Recursion with Count of Nodes Found# We can keep track of number of nodes we have found so far. If nodes found is less than 2, then we will return null.
Code#
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
static class Pair (){
TreeNode root;
int count;
public Pair (TreeNode root, int count) {
this .root = root;
this .count = count;
}
}
public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) {
Pair dfsAns = dfs(root, p, q);
if (dfsAns.count < 2){
return null ;
}
return dfsAns.root ;
}
public Pair dfs (TreeNode root, TreeNode p, TreeNode q) {
if (root == null ) {
return null ;
}
Pair leftAns = dfs(root.left , p, q);
Pair rightAns = dfs(root.right , p, q);
if (root == p || root == q){
return new Pair(root, 1+ leftAns.count + rightAns.count );
}
if (leftAns.root != null && leftAns.root != null ){
return new Pair(root, 2);
}
return leftAns.root != null ? leftAns: rightAns;
}
Method 3 - By Storing root to p and q Paths using backtracking# This approach is same as Lowest Common Ancestor of a Binary Tree#Method 1 - By Storing root to p and q paths using backtracking
Complexity# ⏰ Time complexity: O(n). The tree is traversed twice, and paths are compared. 🧺 Space complexity: O(n)