给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
//方法:递归+二叉搜索树性质+最近公共祖先性质
/*
二叉搜索树:
可以快速地找出树中的某个节点以及从根节点到该节点的路径,例如我们需要找到节点 pp:
我们从根节点开始遍历;
如果当前节点就是 pp,那么成功地找到了节点;
如果当前节点的值大于 pp 的值,说明 pp 应该在当前节点的左子树,因此将当前节点移动到它的左子节点;
如果当前节点的值小于 pp 的值,说明 pp 应该在当前节点的右子树,因此将当前节点移动到它的右子节点。
在寻找节点的过程中,我们可以顺便记录经过的节点,这样就得到了从根节点到被寻找节点的路径。
分别得到了从根节点到 pp 和 qq 的路径之后,我们就可以很方便地找到它们的最近公共祖先了。
显然,pp 和 qq 的最近公共祖先就是从根节点到它们路径上的「分岔点」,也就是最后一个相同的节点。
进一步总结:
若 rootroot 是 pp, qq的 最近公共祖先 ,则只可能为以下情况之一:
1.pp 和 qq 在 rootroot 的子树中,且分列 rootroot 的 异侧(即分别在左、右子树中);
2.pp = root,且 qq 在 rootroot 的左或右子树中;
3.qq = root,且 pp 在 rootroot 的左或右子树中;
所以,
通过递归对二叉树进行先序遍历,当遇到节点 pp 或 qq 时返回。
从底至顶回溯,当节点 pp, qq在节点 rootroot 的异侧时,节点 rootroot 即为最近公共祖先,则向上返回 rootroot 。
*/
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
TreeNode* res=root;
if(p->val<root->val&q->val>root->val)
{
res= root;//pp 和 qq 在 rootroot 的子树中,且分列 rootroot 的 异侧(即分别在左、右子树中);
}
if(p->val==root->val||q->val==root->val)
{
res= root;//pp = root,且 qq 在 rootroot 的左或右子树中;qq = root,且 pp 在 rootroot 的左或右子树中;
}
if(p->val<root->val&&q->val<root->val)
{
res=lowestCommonAncestor(root->left,p,q);//都在左子树中
}
if(p->val>root->val&&q->val>root->val)
{
res=lowestCommonAncestor(root->right,p,q);//都在右子树中
}
return res;
}