题目:
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
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).”
Given 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 LCA 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 LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
Note:
All of the nodes' values will be unique.
p and q are different and both values will exist in the BST.
分析:最直接的思维方式如下:从根节点开始遍历查找节点 p 和 q,并使用两个数组 acl_p, acl_q 记录路径上的节点。遍历完后再查找两个数组中u最后一个相同的节点即可。
代码如下:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL) return NULL;
vector<TreeNode* > acl_p;
vector<TreeNode* > acl_q;
TreeNode* x = root;
while(x->val != p->val){
acl_p.push_back(x);
if (x->val > p->val){
x = x->left;
}
else{
x = x->right;
}
}
acl_p.push_back(x);
x = root;
while(x->val != q->val){
acl_q.push_back(x);
if (x->val > q->val){
x = x->left;
}
else{
x = x->right;
}
}
acl_q.push_back(x);
TreeNode* pre = acl_p[0];
for(int i = 0; i < acl_p.size() && i < acl_q.size(); ++i){
if (acl_p[i]->val == acl_q[i]->val){
pre = acl_p[i];
}
else{
break;
}
}
return pre;
}
方法二:递归
从根节点开始,如果根节点的左子树和右子树能分别找到p 和 q,则说明根节点为最近公共祖先节点(LCA)。否则 LCA 一定处于左子树或右子树中。
代码如下:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root == q){
return root;
}
TreeNode* lFlag = lowestCommonAncestor(root->left, p, q);
TreeNode* rFlag = lowestCommonAncestor(root->right, p, q);
if(lFlag && rFlag){
return root;
}
else if (lFlag){
return lFlag;
}
else{
return rFlag;
}
}
还有一种更简单的非递归版本,如果理解递归方法,那么这种方法也一定能够理解:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while((root->val - p->val) * (root->val - q->val) > 0){
root = root->val > p->val ? root->left : root->right;
}
return root;
}
我突然发现 leetcode 上给出的时间评测并不可靠,同样的代码,会有不同的实行时间,且C++ 版本竟然比 JAVA 版本慢了接近 40 秒,是不是与网速有关系?有合理的解释吗?