二叉树的最近公共祖先
本文最后更新于33 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

🔗 二叉树的最近公共祖先

题目来源236. 二叉树的最近公共祖先 – 力扣(LeetCode)


📌 题目描述

给定一个二叉树,找到该树中两个指定节点 pq最近公共祖先

根据百度百科定义:“对于有根树 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, 10⁵] 内
  • -10⁹ <= Node.val <= 10⁹
  • 所有 Node.val 互不相同
  • p != q
  • p 和 q 均存在于给定的二叉树中

💡 解法:递归搜索 —— O(n) 时间,O(h) 空间

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 终止条件:
        // 1. 当前节点为空;
        // 2. 当前节点为 p 或 q。
        if (root == null || root == p || root == q) {
            return root;
        }

        // 在左子树中查找 p 和 q 的最近公共祖先
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        // 在右子树中查找 p 和 q 的最近公共祖先
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        // 情况 1:p 和 q 分别位于当前节点的左右子树中,则当前节点就是最近公共祖先
        if (left != null && right != null) {
            return root;
        }
        // 情况 2:p 和 q 都不在当前节点的右子树中,则最近公共祖先在左子树中
        if (left == null) {
            return right;
        }
        // 情况 3:p 和 q 都不在当前节点的左子树中,则最近公共祖先在右子树中
        if (right == null) {
            return left;
        }
        
        // 默认返回 null(实际上不会到达这里)
        return null;
    }
}

关键点

  • 递归终止条件:当节点为空或等于 p 或 q 时返回该节点;
  • 递归处理:分别对左右子树进行递归查找;
  • 判断逻辑:若左右子树均非空,则当前节点即为最近公共祖先;否则,返回非空子树的结果。

📊 复杂度分析

  • 时间复杂度O(n)
    每个节点最多被访问一次,故时间复杂度为 O(n),其中 n 是树中节点的数量。
  • 空间复杂度O(h)
    主要取决于递归调用栈的深度,最坏情况下(树退化为链表)为 O(n),平均情况(平衡树)为 O(log n)

🧩 解题思路

核心思想:分治策略

  1. 递归基础:如果当前节点是 null 或者正好等于 pq,则直接返回当前节点。
  2. 递归过程:对当前节点的左右子树分别进行递归查找,寻找 pq 的出现位置。
  3. 合并结果
    • 如果 p 和 q 分别出现在左右子树中,则当前节点即为它们的最近公共祖先;
    • 如果两者都出现在同一侧子树中,则最近公共祖先也在这一侧。

为什么这种递归方法有效?

  • 递归本质:利用了二叉树的天然递归结构,从底部向上逐步确定最近公共祖先。
  • 优化效率:每个节点仅访问一次,避免重复计算,达到线性时间复杂度。
  • 简洁实现:通过简单的递归与条件判断即可解决问题,代码直观易懂。
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇