Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary search tree.
For example, Given the following tree: root = [3,5,1,6,2,0,8,null,null,7,4]
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Input: 3
Explanation: The first common ancestor of node 5 and node 1 is node 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The first common ancestor of node 5 and node 4 is node 5.
Notes:
All node values are pairwise distinct.
p, q are different node and both can be found in the given tree.
Solutions
Solution 1: Recursion
First, we check if the root node is null or if the root node is equal to \(\textit{p}\) or \(\textit{q}\). If so, we return the root node directly.
Then, we recursively search the left and right subtrees to get \(\textit{left}\) and \(\textit{right}\), respectively. If both \(\textit{left}\) and \(\textit{right}\) are not null, it means \(\textit{p}\) and \(\textit{q}\) are in the left and right subtrees, respectively, so the root node is the lowest common ancestor. Otherwise, if either \(\textit{left}\) or \(\textit{right}\) is null, it means both \(\textit{p}\) and \(\textit{q}\) are in the non-null subtree, so the root node of the non-null subtree is the lowest common ancestor.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of nodes in the binary tree.
1 2 3 4 5 6 7 8 91011121314151617
# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = NoneclassSolution:deflowestCommonAncestor(self,root:TreeNode,p:TreeNode,q:TreeNode)->TreeNode:ifrootisNoneorrootin[p,q]:returnrootleft=self.lowestCommonAncestor(root.left,p,q)right=self.lowestCommonAncestor(root.right,p,q)returnrootifleftandrightelseleftorright
1 2 3 4 5 6 7 8 910111213141516171819
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */classSolution{publicTreeNodelowestCommonAncestor(TreeNoderoot,TreeNodep,TreeNodeq){if(root==null||root==p||root==q){returnroot;}TreeNodeleft=lowestCommonAncestor(root.left,p,q);TreeNoderight=lowestCommonAncestor(root.right,p,q);returnleft==null?right:(right==null?left:root);}}
1 2 3 4 5 6 7 8 91011121314151617181920
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */classSolution{public:TreeNode*lowestCommonAncestor(TreeNode*root,TreeNode*p,TreeNode*q){if(!root||root==p||root==q){returnroot;}TreeNode*left=lowestCommonAncestor(root->left,p,q);TreeNode*right=lowestCommonAncestor(root->right,p,q);returnleft&&right?root:(left?left:right);}};
1 2 3 4 5 6 7 8 910111213141516171819202122
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funclowestCommonAncestor(root*TreeNode,p*TreeNode,q*TreeNode)*TreeNode{ifroot==nil||root==p||root==q{returnroot}left:=lowestCommonAncestor(root.Left,p,q)right:=lowestCommonAncestor(root.Right,p,q)ifleft==nil{returnright}ifright==nil{returnleft}returnroot}
1 2 3 4 5 6 7 8 9101112131415161718192021
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } *//** * @param {TreeNode} root * @param {TreeNode} p * @param {TreeNode} q * @return {TreeNode} */varlowestCommonAncestor=function(root,p,q){if(!root||root===p||root===q){returnroot;}constleft=lowestCommonAncestor(root.left,p,q);constright=lowestCommonAncestor(root.right,p,q);returnleft&&right?root:left||right;};