【算法训练-二叉树 五】【最近公共祖先】二叉树的最近公共祖先

news2025/1/12 18:43:16

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【二叉树的节点查找】,使用【二叉树】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。

名曲目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

二叉树的最近公共祖先【MID】

最近公共祖先(Lowest Common Ancestor, LCA)是指在一个二叉树中,两个节点p和q的最低公共祖先节点,即深度最深且同时是p和q的祖先的节点,同时节点本身也可以为其最近公共祖先

题干

在这里插入图片描述

解题思路

根据以上定义,若 root 是 p,q的 最近公共祖先 ,则只可能为以下情况之一:

  1. p 和 q 在 root 的子树中,且分列 root 的 异侧(即分别在左、右子树中);
  2. p=root ,且 q 在 roo的左或右子树中
  3. q=root,且 p 在 root的左或右子树中

在这里插入图片描述

  1. 终止条件:当越过叶节点,则直接返回 null;当 root 等于 p,q,则直接返回 root;
  2. 递推工作: 开启递归左子节点,返回值记为 left;开启递归右子节点,返回值记为 right;
  3. 返回值: 根据 left和 right,可展开为四种情况;
    • 当 left 和 righ同时为空 :说明一直遍历到叶节点, root 的左 / 右子树中都不包含 p,q ,返回 null;
    • 当 left和 right 同时不为空 :说明 pq 分列在 roo的 异侧 (分别在 左 / 右子树),因此 root为最近公共祖先,返回 root
    • 当 left为空 ,right不为空 :pq 都不在 root 的左子树中,直接返回 right。具体可分为两种情况:pq 其中一个在 root 的 右子树 中,此时 right指向 p(假设为 p );pq 两节点都在 root的 右子树 中,此时的 right指向 最近公共祖先节点 ;
    • 当 left不为空 , right为空 :与情况 3. 同理

代码实现

给出代码实现基本档案

基本数据结构二叉树
辅助数据结构
算法递归、DFS
技巧

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

 public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        return dfsFindRoot(root, p, q);
    }

    private TreeNode dfsFindRoot(TreeNode node, TreeNode p, TreeNode q) {
        // 1 递归终止条件:越过叶子节点没找到;root为p或root为q
        if (node == null || node == p || node == q) {
            return node;
        }

        // 2 本级任务:分别在左右子树中寻找节点
        TreeNode left = dfsFindRoot(node.left, p, q);
        TreeNode right = dfsFindRoot(node.right, p, q);

        // 3 本级任务:分别在左右子树中寻找节点
        if (left != null && right != null) {
            //如果两个节点分别存在于左右子树,则当前节点即是最近公共祖先
            return node;
        }
        // 如果两个节点在root的同侧,则返回的节点即为公共节点
        if (right == null && left != null) {
            return left;
        }
        if (right != null && left == null) {
            return right;
        }
        // 如果两个节点左右都没有找到,则返回null
        return null;
    }

复杂度分析

时间复杂度:O(n),其中n为二叉树的节点数,遍历整棵二叉树
空间复杂度:O(n),最坏情况下,二叉树化为链表,递归栈深度最大为n

拓展知识:二叉树的最近公共祖先

最近公共祖先(Lowest Common Ancestor, LCA)是指在一个二叉树中,两个节点p和q的最低公共祖先节点,即深度最深且同时是p和q的祖先的节点。以下是一种基于递归的实现思路,并提供Java的实现代码:

定义

假设有一个二叉树,每个节点包含如下信息:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

实现思路

  1. 从根节点开始遍历二叉树。
  2. 对于当前节点,递归地查找其左子树和右子树,看看是否能找到节点p和节点q。
  3. 如果左子树中找到了节点p或节点q,或者右子树中找到了节点p或节点q,那么当前节点就是它们的最近公共祖先。
  4. 如果左子树和右子树都找到了最近公共祖先,那么当前节点就是它们的最近公共祖先。
  5. 最后,返回最近公共祖先。

Java实现代码

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    // Base case: 如果当前节点为空或者等于p或q中的任意一个,直接返回当前节点
    if (root == null || root == p || root == q) {
        return root;
    }
    
    // 递归查找左子树和右子树
    TreeNode leftLCA = lowestCommonAncestor(root.left, p, q);
    TreeNode rightLCA = lowestCommonAncestor(root.right, p, q);
    
    // 如果左子树和右子树都找到了最近公共祖先,那么当前节点就是最近公共祖先
    if (leftLCA != null && rightLCA != null) {
        return root;
    }
    
    // 如果只在一侧找到了最近公共祖先,返回那一侧找到的结果
    return (leftLCA != null) ? leftLCA : rightLCA;
}

这段代码会在二叉树中查找节点p和q的最近公共祖先,并返回该节点。如果一个节点是另一个节点的祖先,那么它自己也可以是自己的祖先,因此在递归中会检查当前节点是否等于p或q中的任意一个,如果是就返回当前节点。否则,递归地查找左子树和右子树,并根据左右子树的结果确定最近公共祖先。

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

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

相关文章

基于微信小程序的高校就业招聘系统设计与实现(源码+lw+部署文档+讲解等)

前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…

悬崖边:企业如何应对网络安全漏洞趋势

在本文中,我们将讨论企业在处理漏洞时面临的挑战,解释安全漏洞是如何引发网络攻击的,以及为什么它会导致不可接受的事件。我们还将分享我们在识别趋势性漏洞方面的经验。 现代信息安全方法正在成为企业的工作流程。例如,不久前&a…

Visio 无边框保存png和pdf文件

1 无边框保存为png 1 点击【开发工具】- 【显示ShapeSheet】- 【页】 选择【Print Properties】 更改【PageLeftMargin、PageRightMargin、PageTopMargin、PageBottomMargin】的数值,如果改成0,那么就完全没有空白。更改数值后一定要回车! …

Uni-app 调用微信地图导航功能【有图】

前言 我们在使用uni-app时&#xff0c;有时候会遇到需要开发地图和导航的功能&#xff0c;这些方法其实微信小程序的API已经帮我们封装好了 详见&#xff1a;微信小程序开发文档 接下来我们就演示如何用uni-app来使用他们 使用 <template><view><button type…

什么是Vue的自定义指令(custom directives)?如何自定义指令?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Vue.js 的自定义指令⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友…

蓝桥杯 题库 简单 每日十题 day7

01 啤酒和饮料 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。啤酒每罐2.3元&#xff0c;饮料每罐1.9元。小明买了若干啤酒和饮料&#xff0c;一共花了82.3元。我们还知道他买的啤酒比饮料的数量少&#xff0c;请你…

时间任务管理软件OmniFocus 3 mac中文版软件特色

OmniFocus Standard mac是一款高效的任务管理软件&#xff0c;具有任务管理功能、自定义功能、简洁直观的界面以及强大的提醒和通知功能。 OmniFocus Standard mac软件特色 ​任务管理功能&#xff1a;OmniFocus Standard支持多种视图以适应不同的需求和偏好&#xff0c;比如项…

vue3【echarts 做的词云图】

效果图 安装 安装echarts npm install echarts安装词云图 npm install echarts-wordcloudecharts-wordcloud的git仓库地址 echarts官网地址 引用 import * as ECharts from "echarts"; //引用eacharts import echarts-wordcloud;//引用云词这里的echarts 是自己简…

驱动开发 linux内核GPIO子系统、及其新版API的概念和使用,linux内核定时器

1、GPIO子系统 概述&#xff1a;每一个芯片厂商生产出芯片后会给linux提供一个当前芯片中gpio外设的驱动&#xff0c;我们只需要调用对应的厂商驱动就可以完成硬件的控制。而linux内核源码中的gpio厂商驱动有很多&#xff0c;linux内核个会对厂商驱动做一些封装&#xff0c;会…

MyBatis 缓存模块

文章目录 前言缓存的实现Cache接口PerpetualCache 缓存的应用缓存对应的初始化一级缓存二级缓存第三方缓存 前言 MyBatis作为一个强大的持久层框架&#xff0c;缓存是其必不可少的功能之一&#xff0c;Mybatis中的缓存分为一级缓存和二级缓存。但本质上是一样的&#xff0c;都…

第七天:gec6818开发板QT和Ubuntu中QT安装连接sqlite3数据库驱动环境保姆教程

sqlite3数据库简介 帮助文档 SQL Programming 大多数关系型数的操作步骤&#xff1a;1&#xff09;连接数据库 多数关系型数据库都是C/S模型 (Client/Server)sqlite3是一个本地的单文件关系型数据库&#xff0c;同样也有“连接”的过程 2&#xff09;操作数据库 作为程序员&am…

windows下gvim的配置

一、vim配置文件 "查看自己的vimrc所在的目录 "在命令模式下 :echo $MYVIMRC"打开自己的vimrc文件 "在命令模式下 :e $MYVIMRC 二、排版 "查看自己当前的字体及大小 "在命令模式下 :set guifont?"设置默认的字体为仿宋_GB2312&#xff…

蓝桥杯打卡Day12

文章目录 接龙数列冶炼金属 一、接龙数列OJ链接 本题思路:本题是一道经典的dp问题&#xff0c;设第i个数的首位数字是first&#xff0c; 末位数字是last。因为第i个数只可能加到一个以first结尾的接龙数列中使得这个接龙数列长度加1并且结尾数字变成last.所以状态转移方程为d…

让Mac菜单栏变得更加美观整洁——Bartender 5

Bartender 5是一款Mac电脑上的菜单栏图标管理软件&#xff0c;能够帮助您把菜单栏上的图标整理得更加美观、整洁和易于使用。如果您的菜单栏上充斥着许多图标&#xff0c;导致视觉上很不舒适和疲劳&#xff0c;那么Bartender 5就是解决这一问题的最佳选择&#xff01; Bartend…

智能热水器丨打造智能家居新体验

随着科学技术的不断发展&#xff0c;智能电器越来越被大众所采纳&#xff0c;如智能扫地机&#xff0c;智能洗衣机&#xff0c;智能微波炉等等&#xff0c;越来越智能的电器为人们的生活带来了许多便利。以往的热水器一般都是只有按键/机械的控制方式&#xff0c;没有其他无线控…

Python绘制X-bar图和R图 | 统计过程控制SPC

X-bar图和R图是用于统计过程控制&#xff08;SPC&#xff09;的两种常用工具&#xff0c;用于监测过程的平均值和范围&#xff08;变异性&#xff09;。这些图有助于识别过程中的变化和异常&#xff0c;以便及时采取纠正措施。 **X-bar图&#xff08;平均值控制图&#xff09;…

Gitee使用用户名密码登录一直错误/IDEA连接gitee仓库密码错误

天坑,注册的时候名字带了大写,用户名自动给你变成小写 真正的用户名在个人主页里面看,是后面的字符,才是真正的用户名.排查了一个小时密码问题,真的坑

使用扩展运算符(...)合并数组

在项目开发过程中&#xff0c;有一个需求&#xff0c;需要制作一个带有标题的表格&#xff0c;如下所示&#xff1a; 和后端开发沟通时&#xff0c;后端计划返回三个数组&#xff0c;标题写死。所以我需要做的就是把数组合并&#xff0c;然后在三个数组之前增加标题。这里我采用…

入行软件测试多年的心得体会

成为xx一员测试已经有1年半了&#xff0c;一直没有真正坐下来花些时间将自己的思路理清一下。刚好近期公司落地了OKR&#xff0c;给自己制定了OKR之后思路终于开始清晰起来&#xff0c;朦朦胧胧地开始看清了远方的路&#xff0c;麻着胆子分析一下自己&#xff0c;毕竟摸黑走路的…

CIIS 2023丨聚焦文档图像处理前沿领域,合合信息AI助力图像处理与内容安全保障

近日&#xff0c;2023第十二届中国智能产业高峰论坛&#xff08;CIIS 2023&#xff09;在江西南昌顺利举行。大会由中国人工智能学会、江西省科学技术厅、南昌市人民政府主办&#xff0c;南昌市科学技术局、中国工程科技发展战略江西研究院承办。本次大会重点关注AI大模型、生成…