1题目
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
2链接
题目链接:235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)
视频链接:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先_哔哩哔哩_bilibili
3解题思路
在搜索二叉树的公共祖先时,利用回溯从底向上搜索,遇到一个节点的左子树里有p,右子树里有q,那么当前节点就是最近公共祖先。
但是在二叉搜索树中,要利用已有树的顺序。在有序树里,如果判断一个节点的左子树里有p,右子树里有q呢?因为是有序树,所有 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p。
那么只要从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是q 和 p的公共祖先。 那问题来了,一定是最近公共祖先吗?
如图,我们从根节点搜索,第一次遇到 cur节点是数值在[p, q]区间中,即 节点5,此时可以说明 p 和 q 一定分别存在于 节点 5的左子树,和右子树中。
此时节点5是不是最近公共祖先? 如果 从节点5继续向左遍历,那么将错过成为q的祖先, 如果从节点5继续向右遍历则错过成为p的祖先。
所以当我们从上向下去递归遍历,第一次遇到 cur节点是数值在[p, q]区间中,那么cur就是 p和q的最近公共祖先。
如图所示:p为节点6,q为节点9
可以看出直接按照指定的方向,就可以找到节点8,为最近公共祖先,而且不需要遍历整棵树,找到结果直接返回!
递归法:
我不写每一步的流程了,但是要注意:调用递归函数的地方,要return递归函数的返回值。
在二叉树:公共祖先问题 (opens new window)中,如果递归函数有返回值,如何区分要搜索一条边,还是搜索整个树。
搜索一条边的写法:
if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;
搜索整个树写法:
left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;
from opnai:
在递归函数遍历二叉树时,需要根据具体情况来确定是否需要返回递归函数的返回值。通常有以下两种情况:
-
需要返回递归函数的返回值:当递归函数需要返回某些信息或状态时,就需要使用返回值。例如,在查找二叉树中是否存在某个节点时,可以使用递归函数进行遍历,并在找到该节点时返回其指针;如果没有找到,则返回空指针。又例如,在计算二叉树的最大深度时,可以使用递归函数进行遍历,并返回左右子树的最大深度加一的较大值。
-
不需要返回递归函数的返回值:当递归函数只是对当前节点进行操作而不需要返回任何信息或状态时,就不需要使用返回值。例如,在遍历二叉树时,可以使用递归函数进行前序、中序或后序遍历,并在遍历到每个节点时执行某些操作,如打印节点的值或将节点插入到链表中。此时,可以直接调用递归函数而无需使用返回值。
总之,需要根据具体情况来判断是否需要使用递归函数的返回值。如果需要返回信息或状态,则必须使用返回值;否则就可以选择不使用返回值
4代码
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL) return root;
if (root->val > p->val && root->val > q->val) { //说明p、q再cur的左子树
TreeNode* left = lowestCommonAncestor(root->left, p, q);
return left;
}
if (root->val < p->val && root->val < q->val) {
TreeNode* right = lowestCommonAncestor(root->right, p, q);
return right;
}
return root;
}
};