二叉树深度学习——二叉树的最近公共祖先

news2024/10/4 12:32:29

1.题目解析

 题目来源:236.二叉树的最近公共祖先

测试用例 

2.算法原理

基本解法O(N^2)

这里我们可以将寻找的两节点分为在同一子树与不在同一子树的两种情况分析

1.在同一子树:由于自己可以是自己的祖先,所以寻找层数较高的节点就是二者的公共节点

2.不在同一个子树:找到两个节点所在子树个最近一个祖先节点即可

具体思路是:创建一个查找节点的函数,然后从最上面的头结点查找两节点所在的子树,使用递归向下不断查找直到找到为止,然后根据上述的两种情况,不在同一子树返回最近公共祖先,在同一子树则递归查找即可

进阶解法O(logN)

 由于上面的思路时间复杂度为O(N^2),所以我们可以进行优化,这里优化的思路是记录两个节点从最上面的头结点到自己的路径,然后求出两节点路径的交点即可,因为由题目可以知道两个节点一定都在二叉树中,所以可以使用这样的思路

记录路径的方法:首先从头开始不断插入节点,如果在左子树找到该节点则入栈记录路径后直接退出,同理如果在右子树找到也是,若在左右子树都没找到则删除之前在这棵子树记录的路径然后寻找其他子树即可,最后直到找到两个节点,此时两个不同的栈就记录了两节点的路径

找出交点的方法:先让长的栈先删除出栈,直到两个栈长度相同,然后一起出栈删除直到二者的头元素相同然后返回任意一个头元素即可

3.实战代码

基本解法代码: 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool FindInTree(TreeNode* t,TreeNode* x)
    {
        if(t == nullptr)
        {
            return false;
        }

        return t == x
        || FindInTree(t->left,x)
        || FindInTree(t->right,x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root == nullptr)
        {
            return nullptr;
        }
        if(root == p || root == q)
        {
            return root;
        }

        bool pInLeft = FindInTree(root->left,p);
        bool pInRight = !pInLeft;

        bool qInLeft = FindInTree(root->left,q);
        bool qInRight = !qInLeft;

        if((pInLeft && qInRight) || (pInRight && qInLeft))
        {
            return root;
        }
        else if(pInLeft && qInLeft)
        {
            lowestCommonAncestor(root->left,p,q);
        }
        else if(pInRight && qInRight)
        {
            lowestCommonAncestor(root->right,p,q);
        }
        
        return nullptr;
    }
};

进阶解法代码: 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool GetPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& st)
    {
        //节点为空直接返回
        if(root == nullptr)
        {
            return false;
        }

        //不管是什么直接入栈记录路径
        st.push(root);

        //如果找到节点则不用继续寻找该节点的路径
        if(root == x)
        {
            return true;
        }

        //如果没找到节点则继续从该节点的左子树寻找并记录路径
        if(GetPath(root->left,x,st))
        {
            return true;
        }

        //同理去他的右子树寻找并记录数据
        if(GetPath(root->right,x,st))
        {
            return true;
        }

        //如果在左右子树均未找到则这个节点整个子树都不是目标节点的路径
        //删除这个子树后继续寻找其他子树
        st.pop();
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        stack<TreeNode*> pst,qst;
        bool pInTree = GetPath(root,p,pst);
        bool qInTree = GetPath(root,q,qst);

        //让长的路径先删除
        while(pst.size() != qst.size())
        {
            if(pst.size() > qst.size())
            {
                pst.pop();
            }
            else
            {
                qst.pop();
            }
        }

        //同时删除直到找到路径中的共同节点
        while(pst.top() != qst.top())
        {
            pst.pop();
            qst.pop();
        }
        return pst.top();
    }
};

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

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

相关文章

AFSim仿真系统 --- 系统简解_03( Warlock模块 - 人工干预 在仿真领域中指的是AFSIM的操作员互动可视化应用程序)

我们就用保留单词 Warlock Warlock&#xff08;在仿真领域中指的是AFSIM的操作员互动可视化应用程序--人工干预 &#xff09; Warlock是AFSIM的操作员环环相扣&#xff08;Operator-in-the-Loop&#xff09;视觉应用程序。它提供了一个图形环境&#xff0c;用于在运行时查看和…

【知识分享】如何计算开关电路中的RC-Snubber参数

在实际的开关电路中&#xff0c;会存在很多的寄生参数&#xff0c;当高边开关被打开或关闭时&#xff0c;在寄生电感器中积累的能量会在输入回路中引起共振&#xff0c;并且&#xff0c;寄生元件的非常小的值就可以使共振频率超过几百MHz&#xff0c;导致EMI的恶化&#xff0c;…

TCP BIC 的拟合函数分析

前面说了这么多&#xff0c;还没有对 bic 的数学性质进行分析&#xff0c;本文补上。 tcp reno 完全依赖 ack 时钟以 rtt 为单位线性增窗&#xff0c;增窗速度与 rtt 负相关&#xff0c;如何在 rtt 比较大时增加增窗速度&#xff0c;这就是 bic&#xff0c;以二分替换遍历。 …

VirtulBOX Ubuntu22安装dpdk23.11

目录 依赖包安装 Python安装 numa安装 ​编辑Python pip3安装 ​编辑pyelftools安装 meson和ninja安装 ​编辑构建与编译 Meson构建DPDK ​编辑Ninja安装DPDK ​编辑VFIO-PCI驱动安装 大页内存和IOMMU配置 ​编辑VFIO-PCI加载 ​编辑VFIO-PCI驱动绑定 ​编辑dpdk…

数字乡村智慧乡镇整体规划设计解决方案

1. 数字乡村的重要性 数字乡镇作为乡村振兴战略的一部分&#xff0c;通过信息化手段提高农业农村现代化水平&#xff0c;是建设数字中国的重要内容&#xff0c;对保障扶贫成果、促进乡村治理体系和治理能力现代化具有基础支撑作用。 2. 乡镇政府和农户面临的问题 乡镇政府和…

Python内存管理与泄漏排查实战

Python内存管理与泄漏排查实战 Python作为一种高级编程语言&#xff0c;因其易读性和丰富的标准库而备受开发者青睐。然而&#xff0c;随着项目的复杂度增加&#xff0c;内存管理问题可能会影响程序的性能&#xff0c;甚至导致内存泄漏。为了构建健壮且高效的应用程序&#xf…

python爬虫 - 初识爬虫

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、爬虫的关键概念 &#xff08;一&#xff09;HTTP请求与响应 &#xff0…

软件工程-数据流图

数据流图(Data Flow Diagram&#xff0c;DFD)是一种图形化技术&#xff0c;它描绘信息流和数据从输入移动到输出的过程中所经受的变换。 数据流图的设计原则 数据守恒原则&#xff0c;对于任何一个加工来说&#xff0c;其所有输出数据流中的数据必须能从该加工的输入数据流中…

移动应用的界面配置-手机银行APP

设置登录界面为线性布局&#xff0c;组件垂直居中排列设置主页为滚动模式&#xff0c;包括布局、添加背景图片设置按钮样式&#xff0c;包括形状、边框线的宽度和颜色 设置登录界面 设置界面为线性布局&#xff0c;组件垂直居中排列 --android:gravity"center_vertical…

前缀调整——优化连续提示以生成文本

人工智能咨询培训老师叶梓 转载标明出处 大模型微调需要更新并存储模型的所有参数&#xff0c;这不仅增加了存储成本&#xff0c;也使得模型的部署变得复杂。为了解决这一问题&#xff0c;斯坦福大学的Xiang Lisa Li和Percy Liang提出了一种名为“前缀调整”&#xff08;Prefi…

YOLO11改进|注意力机制篇|引入HAT超分辨率重建模块

目录 一、HAttention注意力机制1.1HAttention注意力介绍1.2HAT核心代码 二、添加HAT注意力机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、HAttention注意力机制 1.1HAttention注意力介绍 HAT模型 通过结合卷积特征提取与多尺度注意…

第 22 章 工作面试老大难——锁

22.1 解决并发事务带来问题的两种基本方式 当一个事务想对一条记录做改动时&#xff0c;首先会看看内存中有没有与这条记录关联的锁结构&#xff0c;当没有的时候就会在内存中生成一个锁结构与之关联。 trx 信息&#xff1a;代表这个锁结构是哪个事务生成的。is_waiting&…

【SpringBoot详细教程】-10-SpringBoot整合swagger【持续更新】

&#x1f33f; Swagger2构建Restful API 文档 &#x1f341; Swagger简介 由于SpringBoot能够快速开发、便捷部署等特性&#xff0c;相信有很⼤⼀部分SpringBoot的⽤户会⽤来构建 RESTful API。⽽我们构建RESTfulAPI的⽬的通常都是由于多终端的原因&#xff0c;这些终端会共⽤…

[Python学习日记-37] Python 中的内置函数(下)

简介 在 Python 中有很多内置函数&#xff0c;例如len()&#xff0c;这些函数是Python解释器自带的&#xff0c;可以直接使用。本篇将介绍 O-Z 的内置函数&#xff0c;下图是官方给出的所有 Python 解释器自带的函数 内置函数官方详解&#xff1a;Built-in Functions — Python…

新160个crackme - 073-abexcrackme3

运行分析 需要破解keyfile PE分析 疑似C程序&#xff0c;32位&#xff0c;EP Section是CODE&#xff0c;猜测无壳 静态分析&动态调试 ida搜索字符串&#xff0c;进入函数 call analysis failed&#xff0c;无法查看伪代码 找到上面提示的地址401088&#xff0c;发现是个Exi…

鼓组编写:SsdSample鼓映射 GM Map 自动保存 互换midi位置 风格模板 逻辑编辑器

SsdSample音源的键位映射 方便编写鼓的技巧 可以这样去设置键位关系的面板和钢琴卷帘窗的面板&#xff0c;方便去写鼓。 可以先按GM的midi标准去写鼓&#xff0c;然后比对下鼓的键位映射的关系&#xff0c;去调整鼓。 可以边看自己发b站等处的图文笔记&#xff0c;然后边用电…

订阅ROS2中相机的相关话题并保存RGB、深度和点云图

系统&#xff1a;Ubuntu22.04 ROS2版本&#xff1a;ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…

Deathnote解题过程

主机扫描&#xff0c;发现192.168.1.194 arp-scan -l 端口扫描&#xff0c;发现80和22端口 nmap -sS 192.168.1.194 访问80端口发现自动跳转到http://deathnote.vuln/wordpress添加绑定地址就可以访问了 vim /etc/hosts 192.168.1.194 deathnote.vuln 访问发现并没有什么东西…

IPsec自动方式

文章目录 实验要求实验配置 实验要求 配置 IPsec VPN 采用自动方式同时要满足上网和VPN两种需求使用NAT进行地址映射认证方法和加密算法自行配置采用安全的方法 实验配置 R1&#xff1a; #基本配置 sy sy R1 dhcp enable acl 3001 rule 1 deny ip des 192.168.3.0 0.0.0.255 …

【Python】解密用户代理:使用 Python User Agents 库探索浏览器和设备信息

Python User Agents 是一个专为解析 User Agent 字符串而设计的 Python 库。它能够轻松识别访问设备的类型&#xff08;如移动设备、桌面设备或平板&#xff09;&#xff0c;并获取设备、浏览器、操作系统等详细信息。借助它&#xff0c;开发者可以更好地了解访问用户的设备属性…