二叉树的最近公共祖先
难度:
标签:
题目描述
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出:3 解释:节点5
和节点1
的最近公共祖先是节点3 。
示例 2:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5 解释:节点5
和节点4
的最近公共祖先是节点5 。
因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2 输出:1
提示:
- 树中节点数目在范围
[2, 105]
内。 -109 <= Node.val <= 109
- 所有
Node.val
互不相同
。 p != q
p
和q
均存在于给定的二叉树中。
代码结果
运行时间: 68 ms, 内存: 25.5 MB
/*
* 思路:
* 使用Java Stream和自定义类来保存遍历状态和查找结果。
* 1. 通过流式计算遍历二叉树。
* 2. 使用Optional保存查找结果。
* 3. 如果左子树和右子树都有结果,返回当前节点。
* 4. 否则返回有结果的一边。
*/
import java.util.Optional;
import java.util.stream.Stream;
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return find(root, p, q).orElse(null);
}
private Optional<TreeNode> find(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return Optional.empty();
}
if (root == p || root == q) {
return Optional.of(root);
}
Optional<TreeNode> left = find(root.left, p, q);
Optional<TreeNode> right = find(root.right, p, q);
if (left.isPresent() && right.isPresent()) {
return Optional.of(root);
}
return left.isPresent() ? left : right;
}
}
解释
方法:
该题解采用递归的方式来查找两个节点 p 和 q 的最近公共祖先。递归函数对当前节点 root 进行如下处理:
1. 如果 root 为空,或者 root 等于 p 或 q,则直接返回 root。
2. 递归查找 root 的左子树和右子树,分别得到左子树和右子树中 p 和 q 的最近公共祖先 left 和 right。
3. 如果 left 和 right 都为空,说明在当前子树中没有找到 p 和 q,返回 None。
4. 如果 left 为空,right 不为空,则说明 p 和 q 都在右子树中,返回 right。
5. 如果 right 为空,left 不为空,则说明 p 和 q 都在左子树中,返回 left。
6. 如果 left 和 right 都不为空,说明 p 和 q 分别在左右子树中,则当前节点 root 就是最近公共祖先,返回 root。
时间复杂度:
平均 O(logn),最坏 O(n)
空间复杂度:
平均 O(logn),最坏 O(n)
代码细节讲解
🦆
递归函数中,如果left和right都不为空时,为何可以断定当前root就是最近公共祖先?
▷🦆
在递归查找过程中,返回None的条件是基于什么考虑?是否存在其他情况下应该返回None但没有涵盖的?
▷🦆
在二叉树的结构不是完全二叉树时,节点p和q的位置对算法的效率影响如何?
▷相关问题
二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 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
, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。