The basic idea behind marking the presence of a number in a tree branch is to use the non-null pointer for number FOUND, and null pointer for NOTFOUND.
The call stack winds back once a number (p
or q
) is found, or when the root
is null
. Later one gives a clear indication of absence of the searched number.
There are four possible scenarios:
1.) Both under one parent.
root
/ \
Leftsubtree Rightsubtree
p/q q/p
In this case, in the below code, a moment would come when this is satisfied if(left != null && right != null) return root;
2.) One parent of other.
q/p p/q
/ OR \
Leftsubtree Rightsubtree
p/q q/p
In this case, this will be satisfied if(root == null || root == p || root == q) return root;
3.) Either of them not present in the tree.
This condition would go undetected. As shown in case#2, the function returns immediately without further traversing and looking for its counterpart in the tree below it.
4.) None of them are present in the tree.
First line if(root == null ... return ;
will be executed for each non-existing child. The final result would be null
return, as none of the number would ever be found.
Line by line code explanation.
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root == q) return root;
/* (root == null) This proves that root is not in the branch of tree of our interest. Returning null would means NOTFOUND.*/
/* (root == p || root == q) either p or q or both are found. Returning non-null root would means FOUND. */
/*Check for presence in leftsubtree */
TreeNode left = lowestCommonAncestor(root.left, p, q);
/*Check for presence in rightsubtree */
TreeNode right = lowestCommonAncestor(root.right, p, q);
/* root
/ \
leftsubtree Rightsubtree
p/q q/p
*/
if(left != null && right != null) return root; //both the numbers are found inside tree under root
// left or right subtree OR both don't have p or q. Return the overall find result under root.
return left != null ? left : right;
}