当前位置: 首页 > news >正文

leetcode题解236:二叉树的最近公共祖先

一、题目内容

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

二、题目分析

输入和输出

  • 输入:一个二叉树的根节点 root,以及两个指定节点 p 和 q。

  • 输出:一个二叉树节点,表示 p 和 q 的最近公共祖先。

递归函数 lowestCommonAncestor 的逻辑

  • 基本情况:

    • 如果当前节点为空(root == NULL),返回 NULL。

    • 如果当前节点是 p 或 q,返回当前节点。

  • 递归检查左子树和右子树:

    • 递归调用 lowestCommonAncestor(root->left, p, q),检查左子树中是否存在 p 或 q。

    • 递归调用 lowestCommonAncestor(root->right, p, q),检查右子树中是否存在 p 或 q。

  • 返回结果:

    • 如果左子树和右子树的返回值都不为空,说明 p 和 q 分别在当前节点的左子树和右子树中,当前节点即为最近公共祖先。

    • 如果左子树的返回值不为空,右子树的返回值为空,说明 p 和 q 都在左子树中,返回左子树的返回值。

    • 如果左子树的返回值为空,右子树的返回值不为空,说明 p 和 q 都在右子树中,返回右子树的返回值。

    • 如果左子树和右子树的返回值都为空,说明当前子树中不存在 p 和 q,返回 NULL。

三、解题要点

1. 二叉树的定义

二叉树是一种特殊的树形数据结构,每个节点最多有两个子节点,通常分为左子节点和右子节点。二叉树的结构使得递归方法成为解决许多问题的自然选择。

2. 最近公共祖先的性质

最近公共祖先(LCA)是指在二叉树中,两个节点 p 和 q 的最近公共祖先 x 满足以下条件:

  1. x 是 p 和 q 的祖先(一个节点也可以是它自己的祖先)。

  2. x 的深度尽可能大,即 x 是最接近 p 和 q 的祖先。

3.解题思路

  1. 基本情况

    • 如果当前节点为空(root == NULL),返回 NULL。因为空树中不存在任何节点,自然也没有公共祖先。

    • 如果当前节点是 p 或 q(root == p || root == q),返回当前节点。因为当前节点本身就是 p 或 q,它可能是最近公共祖先,或者至少是 p 或 q 的祖先。

  2. 递归检查左子树和右子树

    • 递归调用 lowestCommonAncestor(root->left, p, q),检查左子树中是否存在 p 或 q。

    • 递归调用 lowestCommonAncestor(root->right, p, q),检查右子树中是否存在 p 或 q。

  3. 返回结果

    • 如果左子树的返回值不为空,且右子树的返回值也不为空(left != NULL && right != NULL),说明 p 和 q 分别在当前节点的左子树和右子树中,当前节点即为最近公共祖先,返回当前节点。

    • 如果左子树的返回值不为空,但右子树的返回值为空(left != NULL && right == NULL),说明 p 和 q 都在左子树中,返回左子树的返回值。

    • 如果左子树的返回值为空,但右子树的返回值不为空(left == NULL && right != NULL),说明 p 和 q 都在右子树中,返回右子树的返回值。

    • 如果左子树和右子树的返回值都为空(left == NULL && right == NULL),说明当前子树中不存在 p 和 q,返回 NULL

    • 如果左子树或右子树的递归调用返回了非空值,说明在该子树中找到了 p 或 q,或者找到了它们的公共祖先。

    • 如果左子树和右子树的递归调用都返回了非空值,说明当前节点是 p 和 q 的最近公共祖先。

四、代码解答

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {// 如果当前节点为空,返回 NULLif (root == NULL) return root;// 如果当前节点是 p 或 q,返回当前节点if (root == q || root == p) return root;// 递归检查左子树TreeNode* left = lowestCommonAncestor(root->left, p, q);// 递归检查右子树TreeNode* right = lowestCommonAncestor(root->right, p, q);// 如果左子树和右子树的返回值都不为空,当前节点即为最近公共祖先if (left != NULL && right != NULL) {return root;}// 如果左子树的返回值不为空,右子树的返回值为空,返回左子树的返回值if (left != NULL && right == NULL) {return left;}// 如果左子树的返回值为空,右子树的返回值不为空,返回右子树的返回值if (left == NULL && right != NULL) {return right;}// 如果左子树和右子树的返回值都为空,返回 NULLreturn NULL;}
};

详细注释

  • 成员函数 lowestCommonAncestor:主函数,用于递归查找两个指定节点的最近公共祖先。

  • 递归函数 lowestCommonAncestor

    • 基本情况:如果当前节点为空,返回 NULL。

    • 递归检查左子树:递归调用 lowestCommonAncestor(root->left, p, q),检查左子树中是否存在 p 或 q。

    • 递归检查右子树:递归调用 lowestCommonAncestor(root->right, p, q),检查右子树中是否存在 p 或 q。

    • 返回结果:根据左子树和右子树的返回值判断当前节点是否为最近公共祖先。

回溯和递归的详细解释

  • 递归:递归是一种函数调用自身的方法,用于解决复杂问题。在本题中,递归用于逐层检查每个节点是否为 p 或 q 的祖先。

  • 终止条件:递归的终止条件是当前节点为空。

  • 回溯:在递归调用返回后,通过返回值恢复到当前节点的状态,确保每次递归返回后,状态正确,不会影响后续的递归调用。

http://www.xdnf.cn/news/869779.html

相关文章:

  • 多层感知器MLP实现非线性分类(原理)
  • UDP包大小与丢包率的关系:原理分析与优化实践
  • 语法--06-- 简单句五大形式、系动词
  • Qwen2.5-VL - Vision Transformer(ViT)的patch 处理
  • 固定资产管理系统 ——仙盟创梦IDE
  • 华为云Flexus+DeepSeek征文|实战体验云服务器单机部署和CCE高可用的架构AI赋能
  • Android studio初体验
  • Android Studio 打包时遇到了签名报错问题:Invalid keystore format
  • Excel高级函数使用FILTER、UNIQUE、INDEX
  • 【产品业务设计】支付业务设计规范细节记录,含订单记录、支付业务记录、支付流水记录、退款业务记录
  • DeepSeek 赋能金融衍生品:定价与风险管理的智能革命
  • 3.3 HarmonyOS NEXT原子化服务开发:卡片设计、轻量部署与场景化编排实战
  • k8s集群安装坑点汇总
  • 02-Redis常见命令
  • 智慧城市建设方案
  • git操作指南
  • git引用概念(git reference,git ref)(简化对复杂SHA-1哈希值的管理)(分支引用、标签引用、HEAD引用、远程引用、特殊引用)
  • SSM 框架核心知识详解(Spring + SpringMVC + MyBatis)
  • 6.04打卡
  • Neo4j 安全深度解析:原理、技术与最佳实践
  • C语言到底使用什么编码
  • C++ 中的 const 知识点详解,c++和c语言区别
  • Java高级 | 【实验二】Springboot 控制器类+相关注解知识
  • 使用python3 批量修改文件名前缀
  • 如何在mac上安装podman
  • Python 开发效率秘籍:PyCharm、VS Code 与 Anaconda 配置与实战全解
  • 微服务商城-用户微服务
  • 网约摩的,杀入市场
  • Python训练营打卡DAY44
  • 【运维实战】使用Nvm配置多Node.js环境!