二叉树——二叉树的最近公共祖先
核心思路
1. 递归终止条件:
- 如果当前节点为null,直接返回null
- 如果当前节点就是p或q,直接返回当前节点(自己是自己的祖先)
2. 递归搜索:
- 递归查找左子树,得到结果left
- 递归查找右子树,得到结果right
3. 判断结果:
- 如果left和right都不为空->当前节点就是最近公共祖先
- 如果只有left不为空->公共祖先在左子树
- 如果只有right不为空->公共祖先在右子树
为什么遇到 root == p 或 root == q 直接 return 当前节点?
核心逻辑:递归是向上传递找到的标记
递归函数的作用定义一定要先记住:
lowestCommonAncestor(root, p, q)
如果以 root 为根的子树中包含 p 或 q,就返回找到的那个节点
如果都不包含,返回null
场景 1:当前节点就是 p
当前节点就是 p,说明:
以它为根的子树一定包含 p,
按照函数职责,直接把自己返回,向上层传递:我找到 p 了。
场景 2:当前节点就是 q
同理,直接返回自己,向上层传递:我找到 q 了。
代码解释
1. 节点定义: 标准二叉树节点,包含值、左孩子、右孩子
2. 递归核心:
- 从根节点开始向下遍历
- 只要在左、右子树中分别找到了p和q,当前节点就是它们的最近公共祖先
- 如果只在一侧子树找到,说明两个节点都在这个子树里,继续向上返回结果
3. 时间复杂度: O(n) —— 最多遍历整棵树一次
4. 空间复杂度: O(n) —— 最多遍历整棵树一次
Java代码实现如下:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
/**
* 查找二叉树中两个节点的最近公共祖先
* @param root 二叉树根节点
* @param p 目标节点1
* @param q 目标节点2
* @return 最近公共祖先节点
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 递归终止:节点为空 或 当前节点就是p/q,直接返回
if (root == null || root == p || root == q) {
return root;
}
// 递归查找左子树
TreeNode left = lowestCommonAncestor(root.left, p, q);
// 递归查找右子树
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 情况1:左右子树都找到节点 → 当前节点就是LCA
if (left != null && right != null) {
return root;
}
// 情况2:左子树找到,右子树没找到 → 返回左子树结果
else if (left != null) {
return left;
}
// 情况3:右子树找到,左子树没找到 → 返回右子树结果
else {
return right;
}
}
}
浙公网安备 33010602011771号