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

news2025/1/20 14:52:40

二叉树的最近公共祖先

  • 题目
  • 思路1
  • 思路2
  • 代码

题目

在这里插入图片描述

思路1

给我们两个二叉树中的节点 找出里面的最近公共祖先

首先我们要分析p q 两点有哪些位置关系

  1. p q在根节点的两侧
    在这里插入图片描述
    此时最近公共祖先就是根节点

  2. 在根节点一侧
    在这里插入图片描述
    此时两个节点都在根节点左侧 此时可以递归二叉树 让root.left成为根节点 也就是图中5的位置 此时p q节点又成了第一种情况

  3. p或q其中一个是根节点
    此时根节点就是最近公共祖先

思路2

我们要找两个节点的公共祖先 也就是说从根节点开始走 会在一个地方分岔 再走各自的最短路
**如果我们的节点有一个指向上一个节点的值 我们原路返回 在两个节点第一次相遇的地方就是他们的最小公共节点 **
**但是这里还有一个问题 我们怎么能知道两个节点返回的速度呢? 也就是说 我们不知道两个节点到根节点的举例的长度是多少 **
解决办法是:因为在分叉前 两个节点所走的路程是相同的 知道分叉后才有可能出现不相同的情况 如果我们判断出两段路径的长度谁长 让长的路径走长短路径的差值步 这样 两个节点到根节点的距离就相同了 他们以同样的速度返回 就会在公共祖先处相遇

那么问题是 二叉树并没有给我们找父节点的索引 我们怎么能找到父节点呢?
这里就要使用我们另一个数据结构——栈 我们把每次的路径保存在栈中 返回的时候 直接弹出栈顶元素即可

问题就转变为 怎样找到两个节点到根节点的最短路径 我们可以采用遍历二叉树的 方法来操作

//找节点到root的最短路径 并放在栈中
//我们采用的是从根节点向下查找我们要获取路径的节点;
public boolean getPath(TreeNode root, TreeNode node, Stack<TreeNode> stack){
        if(root == null){
            return false;//如果节点为空
        }
        stack.push(root);
        //不管三七二十一 压入栈中
        if(root == node){
            return true;
        }//如果根节点等于 我们要找的节点
        boolean ret = getPath(root.left, node, stack);
        //遍历左树 找节点
        if(ret == true){
            return true;
            //如果ret == true 说明此时我们找到了 直接返回true;
        }
		//左树没找见从右树找
        boolean ret2 = getPath(root.right, node, stack);
        if(ret2 == ture){
            return true;
        }
        //找到了返回true

 		//如果左树和右树都没有找到
 		//弹出栈顶元素 因为我们不论是不是要的路径都压入栈 此时不正确就要弹出
        stack.pop();
        return false;
        //表示这个路径没有我们要找的节点
    }

我们把关键的逻辑写了之后 其余部分就比较简单

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

        Stack<TreeNode> s1 = new Stack<>();
        Stack<TreeNode> s2 = new Stack<>();
        getPath(root,p,s1);
        getPath(root,q,s2);
        //创建两个栈 并且分别把p和q的路径存储到栈中

        int size1 = s1.size();
        int size2 = s2.size();
        //求出长度

		//让路径长的栈先走差值步 
        if(size1 > size2){
            int size = size1 - size2;
            while(size != 0){
                s1.pop();
                size--;
            }
        }else{
            int size = size2 - size1;
            while(size != 0){
                s2.pop();
                size--;
            }
        }

		//此时在一起走 如果相同 则返回
        while(!s1.empty() && !s2.empty()){
            TreeNode temp1 = s1.pop();
            TreeNode temp2 = s2.pop();
            while(temp1 == temp2 ){
                return temp1;
            }
        }

        return null;
    }

    public static boolean getPath(TreeNode root, TreeNode node, Stack<TreeNode> stack){
        if(root == null){
            return false;
        }
        stack.push(root);
        if(root == node){
            return true;
        }
        boolean ret = getPath(root.left, node, stack);
        if(ret == true){
            return true;
        }

        boolean ret2 = getPath(root.right, node, stack);
        if(ret2 == true){
            return true;
        }
        stack.pop();
        return false;
    }
}

代码

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null){
            return null;
        }//如果为空树 直接返回

        if(p == root || q == root){
            return root;
        }
        //如果p或q为根节点是第三种情况 直接返回根节点
        TreeNode leftRet = lowestCommonAncestor(root.left,p,q);
        TreeNode rightRet = lowestCommonAncestor(root.right,p,q);
		//递归左树和右树
        if(leftRet != null && rightRet != null){
            return root;
            //如果一个在个根节点左侧 一个在右侧返回根节点 对应第二种情况
        }else if(leftRet != null){
            return leftRet;
            //如果右树不包含节点 直接返回左根节点
        }else{
            return rightRet;
            //反之返回右根节点
        }
    }
}

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

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

相关文章

内存取证小练习-基础训练

这是题目和wolatility2.6的链接 链接&#xff1a;https://pan.baidu.com/s/1wNYJOjLoXMKqbGgpKOE2tg?pwdybww 提取码&#xff1a;ybww --来自百度网盘超级会员V4的分享 压缩包很小&#xff0c;题目也比较简单基础&#xff0c;可以供入门使用 1&#xff1a;Which volatility…

使用auto-gpt来写一篇技术文章(如何部署autogpt+遇到的问题+如何使用)

文章目录 前言一、autogpt本地部署1.clone代码2.启动虚拟环境3.运行项目 二、使用aotogpt生成文章1.人设描述2.设置目标3.文章的生成过程4.文章的生成内容 总结 前言 最近AI技术的发展非常迅猛&#xff0c;尤其是和GPT相关的技术&#xff0c;备受瞩目。近日&#xff0c;Autogp…

nvm安装管理npm

1.根据http://t.csdn.cn/mRwCQ这个教程完成安装 2.使用nvm install [指定版本号]&#xff0c;下载了16.15.1&#xff0c;和10.15.1版本 2.5 这里其实出了一点问题&#xff0c;我在下载16.15.1时&#xff0c;因为墙的问题其实是下载出错&#xff0c;报了一个error的&#xff0c…

手推A Unified Solution to Constrained Bidding in Online Display Advertising论文

A Unified Solution to Constrained Bidding in Online Display Advertising&#xff1a;一种对在线展示广告约束出价问题的通用解决方案 未开放但是可以搜到 NeuralAuction: 电商广告中的端到端机制优化方法 https://arxiv.org/abs/2106.03593 一种使用真负样本的在线延迟反…

JVM,关于JVM基础的知识,你确定不了解一下吗?

目录 一.JVM的概念 什么是JVM&#xff1f; 二.JVM的运行流程 1.class文件如何被JVM加载并运行 2.JVM运行时数据包括哪些区域&#xff08;M&#xff09; 三.类加载的过程&#xff08;M&#xff09; 四.双亲委派模型 1.双亲委派模型分析 2.JAVA中有哪些类加载器&#xf…

Maven私服搭建

为什么要搭建私服 通常在maven项目的pom.xml文件中引入了某个依赖包之后&#xff0c;maven首先会去本地仓库去搜索&#xff0c;本地仓库搜索不到会去maven的配置文件settings.xml中配置的maven镜像地址去找&#xff0c;比如&#xff1a; <mirrors><!-- mirror| Specif…

动态规划 --- 电线布设

动态规划 — 电线布设 题目描述 说是话&#xff0c;刚看到也是很懵逼&#xff0c;不想交子集是什么&#xff1f;乱七八糟的连线。 其实仔细想想后&#xff0c;觉得题目应该是说给定了这些点的连接端点&#xff0c;然后从他给的连线中选择出不想交的且条数最多的连线&#x…

Flink自定义函数之标量函数(UDF函数)

1.背景 flink本身给我们提供了大量的内置函数&#xff0c;已经能满足我们绝大部分的需求&#xff0c;但是如果确实是碰到了一些特殊的场景&#xff0c;无法满足我们的需求的时候&#xff0c;我们可以使用自定义函数来解决。 自定义函数大致可以分为标量函数&#xff08;UDF函…

Linux-安装Python2.7

一、简介 正常情况下&#xff0c;使用sudo apt install python来安装就好了。如果发现这个指令报错了&#xff0c;此时就需要手动安装Python2.7了。例如报错如下&#xff1a; 二、实操 1.下载Python2.7的相关源码&#xff08;以2.7.18为例&#xff09; 下载地址如下&#xff1a…

Linux第四章

文章目录 前言一、快捷键小技巧二、软件安装三、systemctl控制软件启动关闭四、软链接五、日期和时区六、ip地址和主机名七、配置linux固定ip地址八、网络请求和下载九、端口十、进程管理十一、主机状态监控十二、环境变量十三、linux文件的上传和下载十四、压缩和解压总结 前言…

第五章 使用RAID与LVM磁盘阵列技术

第五章 使用RAID与LVM磁盘阵列技术 一、RAID磁盘冗余阵列 1、部署磁盘阵列 &#xff08;1&#xff09;、RAID0、1、5、10方案技术对比 RAID级别最少硬盘可用容量读写性能安全性特点02nn低追求最大容量和速度&#xff0c;任何一块盘损坏&#xff0c;数据全部异常。12n/2n高追…

魔兽世界服务端用户注册以及网页的搭建教程

魔兽世界服务端用户注册以及网页的搭建教程 大家好我是艾西&#xff0c;上一章我们讲解了怎么编译一个魔兽的服务端以及安装最后进到我们自己的游戏。那么在平时娱乐的同时肯定是需要和朋友们一起玩游戏才会更有意思&#xff0c;那么今天艾西教大家怎么搭建用户注册页面以及网…

java进程引发的内存泄露问题排查分析

近期工作过程中遇到了一次容器内存不断增高&#xff0c;最终达到90%引发告警的情况。 特征1&#xff0c;把监控面板时间轴拉长会发现&#xff0c;重启后内存占用78%左右&#xff0c;每天增长1%&#xff0c;大约2周后会涨到90%触发告警&#xff08;即如果2周内有代码发布部署&am…

2022-04-27:用go语言重写ffmpeg的remuxing.c示例。

2022-04-27&#xff1a;用go语言重写ffmpeg的remuxing.c示例。 答案2022-04-27&#xff1a; ffmpeg的remuxing.c是一个用于将多媒体文件从一种容器格式转换为另一种容器格式的命令行工具。它可以将音频、视频和字幕等元素从源文件中提取出来&#xff0c;并按照用户指定的方式…

构造函数和析构函数

1.构造函数 1.1 .构造函数概括 、构造函数是一个特殊的成员函数&#xff0c;名字与类名相同,创建类类型对象时由编译器自动调用&#xff0c;以保证每个数据成员都有 一个合适的初始值&#xff0c;并且在对象整个生命周期内只调用一次。 构造函数是特殊的成员函数&#xff0c…

简单认识 Postman界面操作

查看本文前 您需要先登录Postman 如果还没有处理好 可以先查看我的文章 Postman登录注册指导 右上角的 Home 代表主页 就是我们现在看到的这个界面 Workspaces 是一个工作空间管理 这里 我们选择进入 我的工作空间 之后 我们所有的接口请求 就都是在这一块完成的 Collection…

ubuntu中安装VMware Tools,实现Windows文件拖入Ubuntu

ubantu作为一款非常好用的Linux发行版本&#xff0c;深受广大开发者的喜爱&#x1f603;&#xff0c;为了开发的方便&#xff0c;人们常常在windows电脑中安装VMware虚拟机来运行Linux系统&#xff0c;我们时常会遇到这样一种情况&#xff1a;无法互传虚拟机与主机文件。 原因就…

终端连接工具Tabby的下载、安装与配置

目录 一、终端连接工具Tabby的下载1.1、Tabby的下载地址1.2、Tabby的下载步骤 二、终端连接工具Tabby的安装三、终端连接工具Tabby的SSH连接四、终端连接工具Tabby的SFTP 传输工具4.1、服务器上的文件传输到本地电脑4.2、本地电脑的文件传输到服务器 五、终端连接工具Tabby的设…

基于网络爬虫和SpringBoot框架的晋江文学小说小型网站项目

一、Python网路爬虫技术的设计与实现 Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架&#xff0c;常可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程序中。项目中&#xff0c;主要采取Scrapy框架实现一个爬虫&#xff0c;抓…

JavaSE3(4/26)

目录 1.线程的状态 2.线程安全问题 3.synchronized的具体用法 4. 1.线程的状态 首先明白进程的状态:就绪或者阻塞 上述说的就绪和阻塞其实是针对系统中的线程状态(PCB) Java中对于Thread类中的线程的状态进行了进一步的细化 NEW: Thread对象有了,但是线程还没有被执行 TERMI…