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

2023-09-22 09:24:23

⭐️ 题目描述

在这里插入图片描述


🌟 leetcode链接:二叉树的最近公共祖先

思路1: 依次遍历每一个结点,遍历到当前根结点,再继续递归找 p 是否存在左子树 q 是否存在右子树,若 p 在左子树 q 在右子树或者 q 在左子树 p 在右子树,说明当前 root 就是 q p 的公共祖先,若当前结点找不到这种情况,则当前 root 转换为子问题 root->left root->right 继续递归寻找。

1️⃣ 代码:

class Solution {
public:
    bool subTreeFind (TreeNode* root , TreeNode* key) {
        if (root == nullptr) {
            return false;
        }

        if (root == key) {
            return true;
        }

        return subTreeFind(root->left , key) || subTreeFind(root->right , key);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == nullptr) {
            return nullptr;
        }

        // 当前结点可能就是公共祖先
        if (root == p || root == q) {
            return root;
        }

        // 方法1
        // 检查当前子树的左子树是否存在p且当前子树的右子树是否存在q
        // 或者 当前子树的左子树是否存在q且当前子树的右子树是否存在p
        
        // 时间复杂度 O(H * N)  N个结点 每个结点都要找左子树和右子树
        // 
        bool pInLeft = subTreeFind(root->left , p);
        bool pInRight = !pInLeft;   // 不在左子树则必在右子树
        bool qInLeft = subTreeFind(root->left , q);
        bool qInRight = !qInLeft;   // 不在左子树则必在右子树

        if (pInLeft && qInRight) {  // p在左 q在右 当前节点就是他们的公共祖先
            return root;
        }
        if (qInLeft && pInRight) {
            return root;
        }

        // 根节点不存在 转换为子问题 找左子树和右子树
        TreeNode * leftParent = lowestCommonAncestor(root->left , p , q);
        if (leftParent)
            return leftParent;
        TreeNode* rightParent = lowestCommonAncestor(root->right , p , q);
        if (rightParent)
            return rightParent;
        
        // 一定存在
        return nullptr;
    }
}

思路2: 使用两个栈分别存 p q 的结点路径,假设 root = [3,5,1,6,2,0,8,null,null,7,4] , p = 5 , q = 4pStack = {3 , 5} qStack = {3 , 5 , 2 , 4},存好路径之后转换为链表相交问题,让大的先走差距步,qStack = {3 , 5} 在依次比较是否相等,若不相等则继续都出栈继续比较,相等则返回即可。
ps: 并不用判断无公共祖先的情况,因为 p q 都存在于二叉树中。
在这里插入图片描述

2️⃣ 代码:

class Solution {
public:
	bool inorderSearchPath (TreeNode* root, TreeNode* key , stack<TreeNode*>& path) {
        if (root == nullptr) {
            return false;
        }

        path.push(root);    // 入栈
        if (root == key) {
            return true;
        }

        if (inorderSearchPath(root->left , key , path)) {
            return true;
        }
        if (inorderSearchPath(root->right , key , path)) {
            return true;
        }
        
        // 来到这里 说明左右结点都不存在 说明当前父节点也不在路径之中
        path.pop(); // 出栈
        return false;
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath;
        stack<TreeNode*> qPath;
        inorderSearchPath(root , p , pPath);
        inorderSearchPath(root , q , qPath);

        // 链表相交
        // 大的先走差距步
        while (pPath.size() > qPath.size()) {
            pPath.pop();
        }

        while (qPath.size() > pPath.size()) {
            qPath.pop();
        }

        while (pPath.top() != qPath.top()) {
            pPath.pop();
            qPath.pop();
        }

        // 一定存在
        return pPath.top();
    }
}

更多推荐

python温度转换程序

1.使用pycharm运行温度转换程序,尝试将温度单位设在前面2.参照温度转换程序,自己写一个关于货币转换、长度转换、重量转换或者面积转换的程序循环+函数defconvertemperature():temperature=""while(temperature!="q"):temperature=input("请输入

如何在linux定时备份opengauss数据库(linux核心至少在GLIBC_2.34及以上)

前提环境,linux的核心至少在GLIBC_2.34及以上才能使用。查看linux的glibc版本的命令如下strings/lib64/libc.so.6|grepGLIBC如下图或者用ldd--version如下图在官网下载对应的依赖包,只需要这个lib文件即可,将这个包放在linux对应下面脚本的LD_LIBRAR

Guava Cache介绍-面试用

一、GuavaCache简介1、简介GuavaCache是本地缓存,数据读写都在一个进程内,相对于分布式缓存redis,不需要网络传输的过程,访问速度很快,同时也受到JVM内存的制约,无法在数据量较多的场景下使用。基于以上特点,本地缓存的主要应用场景为以下几种:对于访问速度有较大要求存储的数据不经常变化数据量不大,占用

【校招VIP】java语言考点之反射

考点介绍:java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为lava语言的反射机制。反射被视为动态语言的关键。java语言考点之反射

【云服务器开放端口详细教程~来了】

你不知道我真的会哭云服务器开放端口详细教程来了前言一、常见云服务器端口的认识●云服务器端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。●当一台计算机启动了一个可访问的程序,那么它就要至少开启一个端口号来让外界的计算机完成访问。我们可以把没

Linux:haproxy部署--搭建nginx集群

Haproxy介绍Haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备、虚拟主机、基于TCP和HTTP应用代理等功能。其配置简单,而且拥有很好的对服务器节点的健康检查功能(相当于keepalived健康检查),当其代理的后端服务器出现故障时,Haproxy会自动的将该故障服务器摘除,当

爬虫获取静态网页数据

自动爬取网页数据正常情况下是我们使用浏览器输入指定url,对服务器发送访问请求,服务器返回请求信息,浏览器进行解析为我们看到的界面,爬虫就是使用python脚本取代正常的浏览器,获取相应服务器的返回请求信息,并配合python强大的库进行解析分析,能够快速高效地帮助我们进行大数据分析。不需要登录即可返回请求以爬取虎牙交

月木学途开发 3.博客模块开发

概述效果展示数据库设计专栏表DROPTABLEIFEXISTS`blog_column`;CREATETABLE`blog_column`(`blogColumnId`int(11)NOTNULLAUTO_INCREMENT,`blogColumnName`varchar(255)DEFAULTNULL,`blogCo

功能测试如何编写测试用例

测试用例的编写需要按照一定的思路进行,而不是想到哪写到哪,一般测试机制成熟的公司都会有公司自己自定义的测试用例模板,以及一整套的测试流程关注点,当然我们自己在测试生涯中也应当积累一套自己的测试框架,所有功能性的测试都可以依据框架的思路来进行,达到事半功倍的效果。功能测试框架可以包括:界面友好性测试、功能测试、链接测试、

【Web3】创作者经济

这里写目录标题创作者经济是什么?创作者从Web1.0到Web3.0的演进Web1.0企业1985Web2.0平台的创作者2004Web3.0创造者/所有者2021粉丝经济的转变&四个阶段创作者经济的四个阶段创作者经济Web3.0工具创作者经济生态全景图OpenSeaFoundationPleasrDAONiftyPix

从 Hackathon 战队到创业公司,和开发者们聊聊真实世界 AI Apps 的基础设施丨活动预告

在不久前结束的TiDBFutureAppHackathon2023上,来自全球88个国家的1492名参赛者们借助AI和TiDBServerless的能力,构建了许多令人印象深刻的项目。打造Hackathon的项目是一个从0-1的过程,真实世界中也涌现出了一批创业公司正在围绕AI打造创新应用,并实现了规模化,取得了商业成

热文推荐