题目来源:LeetCode236:二叉树的最近公共祖先
问题抽象: 在二叉树中查找两个指定节点的最近公共祖先(LCA)(深度最大的共同祖先节点),需满足以下核心需求:
-
LCA 定义:
- 节点
T是p和q的最近公共祖先,当且仅当:p和q均存在于T的子树中;T的所有子节点均不满足此条件(即T是深度最大的此类节点);
- 特例:若
p是q的祖先,则p为 LCA(反之亦然)。
- 节点
-
输入约束:
- 二叉树节点值唯一,且
p ≠ q; p和q均存在于树中(无需校验不存在情况);- 树节点数范围
[2, 10^5]。
- 二叉树节点值唯一,且
-
算法要求:
- 时间复杂度 O(n)(遍历所有节点,
n为节点数); - 空间复杂度 O(h)(递归栈深度,
h为树高,最坏O(n)); - 禁止存储父指针或修改树结构。
- 时间复杂度 O(n)(遍历所有节点,
-
核心判定规则:
- 递归搜索:
- 若当前子树同时包含
p和q,则返回其 LCA; - 若仅含其一,则返回该节点(向上传递存在性);
- 若当前子树同时包含
- 终止条件:
- 当前节点为
null时返回null; - 当前节点为
p或q时直接返回自身。
- 当前节点为
- 递归搜索:
-
边界处理:
- 树为空时返回
null(但题目保证树非空); p或q为根节点时,根节点即为 LCA;- 典型结构:
p和q分居某节点左右子树 → 该节点为 LCA;p和q位于同侧 → LCA 为更靠近根节点的祖先。
- 树为空时返回
输入:二叉树根节点 root ;目标节点 p, q(TreeNode 类型)
输出: TreeNode(最近公共祖先节点)
解题思路
核心思想: 使用递归深度优先搜索(DFS)遍历二叉树,通过后序遍历的特性自底向上查找目标节点。
- 递归终止条件:
- 当前节点为空(
null)时返回null。 - 当前节点是
p或q时直接返回当前节点(说明找到目标节点)。
- 当前节点为空(
- 递归左右子树:
- 在左子树中搜索
p和q,结果记为left。 - 在右子树中搜索
p和q,结果记为right。
- 在左子树中搜索
- 结果判断:
- 若
left和right均不为空 → 当前节点是最近公共祖先(p和q分布在左右子树)。 - 若
left不为空 → 返回left(p和q均在左子树)。 - 若
right不为空 → 返回right(p和q均在右子树)。 - 若都为空 → 返回
null(题目保证节点存在,实际不会发生)。
- 若
时间复杂度: O(n)(每个节点最多访问一次)。空间复杂度: O(h)(递归栈深度,h 为树的高度)。
代码实现(Java版)🔥点击下载源码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 递归终止条件:遇到空节点或找到目标节点
if (root == null || root == p || root == q) {
return root;
}
// 递归搜索左子树
TreeNode left = lowestCommonAncestor(root.left, p, q);
// 递归搜索右子树
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 左右子树均找到目标节点 → 当前节点为最近公共祖先
if (left != null && right != null) {
return root;
}
// 返回非空子树的结果(若左子树找到则返回left,否则返回right)
return left != null ? left : right;
}
}
代码说明
- 递归终止条件:
- 当
root为null时返回null,避免空指针异常。 - 当
root等于p或q时直接返回,说明当前子树包含目标节点。
- 当
- 左右子树递归:
- 通过
left和right分别记录左右子树的搜索结果。
- 通过
- 结果合并逻辑:
left和right均非空:p和q分布在左右子树,当前节点为最近公共祖先。- 单侧非空:返回非空结果(即已找到的最近公共祖先)。
- 效率优化:
- 无额外数据结构操作,直接利用递归栈回溯结果。
- 每个节点仅访问一次,时间复杂度为 O(n)。
提交详情(执行用时、内存消耗)

1933

被折叠的 条评论
为什么被折叠?



