当前位置: 首页 > 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 的祖先。

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

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

相关文章:

  • Elasticsearch中什么是分析器(Analyzer)?它由哪些组件组成?
  • JS利用原型链实现继承
  • 【leetcode】9. 回文数
  • (每日一道算法题)求根节点到叶节点数字之和
  • Java-IO流之字符输出流详解
  • qiankun模式下 主应用严格模式,子应用el-popover 点击无效不显示
  • GAN训练困境与模型分类:损失值异常与生成判别模型差异解析
  • 第八部分:第六节 - 状态管理 (基础):协调多个界面的状态
  • 基于 ShardingSphere + Seata 的最终一致性事务完整示例实现
  • 局部变量-线程安全
  • 深度学习项目之RT-DETR训练自己数据集
  • 【docker】容器技术如何改变软件开发与部署格局
  • CMake在VS中使用远程调试
  • PocketFlow 快速入门指南
  • 【仿生】硬件缺失,与组装调试,皮肤问题
  • 【C/C++】入门grpc的idl
  • 【算法训练营Day06】哈希表part2
  • 研究探析 | 高速摄像机在一种新型冲击压痕技术及其动态标定方法中的应用
  • 「Java教案」顺序结构
  • 深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
  • 南通购物网站建设/怎么优化网站
  • jsp做网站开发/白杨seo
  • 如何更换wordpress域名/咸阳seo公司
  • jsp网站开发环境配置/广告推广网站
  • 厦门建站价格/广告推广策划
  • 什么网站做一手房好/淘宝关键词搜索量排名