The nearest common ancestor of binary search tree
Given a binary search tree, the nearest common ancestor of two specified nodes in the tree is found.
The definition of the nearest common ancestor is: "for two nodes p and q with root tree T, the nearest common ancestor is expressed as a node x, which satisfies that x is the ancestor of p and q and the depth of X is as large as possible (a node can also be its own ancestor)."
For example, given the following binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
Example 1:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Output: 6 Explanation: the most recent common ancestor of nodes 2 and 8 is 6.Example 2:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Output: 2 Explanation: the closest common ancestor of node 2 and node 4 is 2, because according to the definition, the closest common ancestor node can be the node itself.Explain:
- The values of all nodes are unique.
- p and q are different nodes and exist in a given binary search tree.
Answer
Method 1Using the property of binary search tree, we find the nearest ancestor from the root node of the tree, and set the larger value of p,q as pv, and the smaller value as qv. It can be divided into the following situations
- If the value of the current node is > PV, the common ancestor can be found in the right subtree of the current subtree.
- If the value of the current node is < QV, the common ancestor is found in the left subtree of the current subtree;
- If the value of the current node is > QV and < PV, the common ancestor is the current node.
- In other cases, the common ancestor is between P and Q. it is enough to find a node with the same value as one of them.
C++ code
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* recursion(TreeNode* root,TreeNode* p,TreeNode* q) { if(!root) return nullptr; int v1 = p->val; int v2 = q->val; if(root->val > v1 && root->val < v2) return root; if(root->val > v2) return recursion(root->left,p,q); if(root->val < v1) return recursion(root->right,p,q); return root->val == v1 ? p : q; } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(!root) return nullptr; if(p->val > q->val) swap(p,q); TreeNode* res = recursion(root,p,q); return res; } };
Python code
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def findNode(self,node: TreeNode,a: int,b: int): if not node: return None tmp = node.val if tmp >= a and tmp <= b: return node elif tmp < a: return self.findNode(node.right,a,b) elif tmp > b: return self.findNode(node.left,a,b) def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': pa = min(p.val,q.val) pb = max(p.val,q.val) return self.findNode(root,pa,pb)
For the other two methods, see The nearest common ancestor of a binary tree .