BM38-在二叉树中找到两个节点的最近公共祖先

news2024/9/20 8:36:08

题目

给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。

数据范围:树上节点数满足 1≤n≤10^5  , 节点值val满足区间 [0,n)

要求:时间复杂度 O(n)

注:本题保证二叉树中每个节点的val值均不相同。

如当输入{3,5,1,6,2,0,8,#,#,7,4},5,1时,二叉树{3,5,1,6,2,0,8,#,#,7,4}如下图所示:

所以节点值为5和节点值为1的节点的最近公共祖先节点的节点值为3,所以对应的输出为3。

节点本身可以视为自己的祖先。

示例1

输入:{3,5,1,6,2,0,8,#,#,7,4},5,1

返回值:3

示例2

输入:{3,5,1,6,2,0,8,#,#,7,4},2,7

返回值:2


思路1:非递归写法

要想找到两个节点的最近公共祖先节点,可以从两个节点往上找,每个节点都往上走,一直走到根节点,那么根节点到这两个节点的连线肯定有相交的地方,如果是从上往下走,那么最后一次相交的节点就是他们的最近公共祖先节点。

  1. 层序遍历二叉树(BFS),记录遍历到的每个节点的父节点,存储在Map中,当两个节点o1,o2都遍历到为止。
  2. 从o1节点开始一直到根节点,记录o1节点和它的祖先节点的值,存入ancestors中。
  3. 查看o1节点和它的祖先节点是否包含o2节点,如果不包含再看是否包含o2节点的父节点......
  4. 第一次包含的节点,即是o1和o2的公共祖先节点。

代码1

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        //记录遍历到的每个节点的父节点存入Map中
        Map<Integer, Integer> parent = new HashMap<>();
        //队列作为辅助
        Queue<TreeNode> queue = new LinkedList<>();
        //先将根节点存入Map和queue中
        parent.put(root.val, Integer.MIN_VALUE); //根节点没有父节点,给它默认一个值
        queue.add(root);

        //直到两个节点都找到为止
        while (!parent.containsKey(o1) || !parent.containsKey(o2)) {
            //队列是一边进一边出,这里poll方法是出队
            TreeNode node = queue.poll();
            if (node.left != null) {
                //左子节点不为空,记录下它的父节点
                parent.put(node.left.val, node.val);
                //左子节点不为空,把它加入到队列中
                queue.add(node.left);
            }
            //右节点同上
            if (node.right != null) {
                parent.put(node.right.val, node.val);
                queue.add(node.right);
            }
        }

        Set<Integer> ancestors = new HashSet<>();
        //记录下o1和它的祖先节点,从o1节点开始一直到根节点
        while (parent.containsKey(o1)) {
            ancestors.add(o1);
            o1 = parent.get(o1);
        }
        //查看o1和它的祖先节点是否包含o2节点,如果不包含再看是否包含o2的父节点……
        while (!ancestors.contains(o2)) {
            o2 = parent.get(o2);
        }
        //最先相交的节点即是o1和o2的最近公共祖先节点
        return o2;
    }
}
  • 时间复杂度:O(n),n是二叉树节点的个数,最坏情况下每个节点都会被访问一遍。
  • 空间复杂度:O(n),一个是BFS需要的队列,一个是父子节点关系的map。

思路2:递归写法​​​​​​​


代码2

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */
    public int lowestCommonAncestor(TreeNode root, int o1, int o2) {
        return helper(root, o1, o2).val;
    }

    public TreeNode helper(TreeNode root, int o1, int o2) {
        if (root == null || root.val == o1 || root.val == o2) {
            return root;
        }

        TreeNode left = helper(root.left, o1, o2);
        TreeNode right = helper(root.right, o1, o2);

        //如果left为空,说明这两个节点在root结点的右子树上,只需要返回右子树查找的结果即可
        if (left == null) {
            return right;
        }
        //同上
        if (right == null) {
            return left;
        }
        
        //如果left和right都不为空,说明这两个节点一个在root的左子树上,一个在root的右子树上,只需要返回cur结点即可。
        return root;
    }
}
  • 时间复杂度:O(n),n是二叉树节点的个数,最坏情况下每个节点都会被访问一遍。
  • 空间复杂度:O(n),因为是递归,取决于栈的深度,最差最差情况下,二叉树退化成链表,栈的深度是n。

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

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

相关文章

深入理解Javascript事件处理机制

深入理解javascript事件处理机制 前言 在开发web应用程序时&#xff0c;事件处理机制是javascript中至关重要的一部分。许多高级特性&#xff0c;如事件冒泡、事件捕获和事件委托&#xff0c;都是通过事件处理来实现的。熟练掌握这些技术可以帮助我们更好地组织代码、提高代码…

腾讯多媒体实验室画质增强技术的前沿应用

全真互联时代&#xff0c;音视频技术内核不断更新迭代&#xff0c;LiveVideoStackCon 2022 北京站邀请到腾讯多媒体实验室视频技术研发负责人——夏珍&#xff0c;与大家分享画质增强技术的一些前沿探索和应用研究&#xff0c;在经典影像中非常重要的画质提升技术人脸修复和去压…

告别web.xml映射Servlet、Filter、Listener,解锁注解新方式开发

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 服务器软件&#xff1a;apache-tomcat-8.5.27 目录 一. Servlet、Filter、Listener的注解方式是什么&#xff1f;二. 为什么要使用Servlet、Filter、Listener的注解方式&#xff1f;三…

【架构】互联网应用开发架构演进历程

文章目录 一、背景二、技术架构演进史三、架构演进一: 早期雏形四、架构演进二: 数据库开发&#xff08;LAMP特长&#xff09;五、架构演进三: javaweb的雏形六、架构演进四: javaweb的集群发展​七、架构演进五: javaweb的分布式发展八、架构演进六: javaweb的微服务发展​8.1…

开源 AI 辅助编程工具 AutoDev 现已上架 Jetbrains 插件市场

我们非常高兴地宣布 AutoDev v0.2.0 的发布&#xff01;AutoDev 是一款强大的 AI 辅助编程工具&#xff0c;可以与 Jetbrains 系列 IDE 无缝集成&#xff08;VS Code 支持正在开发中&#xff09;。通过与需求管理系统&#xff08;如 Github Issue 等&#xff09;直接对接&#…

WPF教程(八)--数据绑定(1)--基础概述

使用WPF可以很方便的设计出强大的用户界面&#xff0c;同时 WPF提供了数据绑定功能。WPF的数据绑定跟Winform与ASP.NET中的数据绑定功能类似&#xff0c;但也有所不同&#xff0c;在 WPF中以通过后台代码绑定、前台XAML中进行绑定&#xff0c;或者两者组合的方式进行数据绑定。…

用python制作剪刀石头布的小游戏

1 问题 在python中我们学习了条件语句&#xff0c;那么我们是否可以通过python中条件判断的功能来写出可以判断胜负的剪刀石头布小游戏呢? 2 方法 导入随机函数&#xff0c;保证胜负的随机性 设置对应数值&#xff0c;写好判断输赢的条件语句 运行并查看结果 代码清单 1 impor…

斯坦福| ChatGPT用于生成式搜索引擎的可行性

文&#xff5c;智商掉了一地 随着 ChatGPT 在文本生成领域迈出了重要一步&#xff0c;Bing 浏览器也接入了聊天机器人功能&#xff0c;因此如何保证 Bing Chat 等搜索引擎结果的精确率和真实性也成为了搜索领域的热门话题之一。 当我们使用搜索引擎时&#xff0c;往往希望搜索结…

教你如何进行DNS域名解析

目录 一:DNS系统介绍 1.DNS服务概述 2.DNS域名空间介绍 3.DNS 域名结构 4.DNS解析方式 5.DNS查询方式 &#xff08;1&#xff09;递归查询 &#xff08;2&#xff09;迭代查询 6.DNS服务器类型&#xff1a; (1)主域名服务器 (2)从域名服务器 (3)缓存域名服务器 (4)…

Android进阶宝典 -- 解读Handler机制核心源码,让ANR无处可藏

其实ANR核心本质就是让UI线程&#xff08;主线程&#xff09;等了太久&#xff0c;导致系统判定在主线程做了耗时操作导致ANR。当我们执行任何一个任务的时候&#xff0c;在Framework底层是通过消息机制来维护任务的分发&#xff0c;从下面这个日志可以看到&#xff0c; "…

thrift、go与php

学习一下thrift。 环境 mac m1&#xff0c;go 1.20&#xff0c;php 7.4&#xff0c;thrift 0.18.1 要学习thrift&#xff0c;第一步得先安装 $ brew install thrift学习的计划是用go作为server&#xff0c;php作为client&#xff0c;通过thrift的方式完成一次请求demo。 建…

Java语言的特点和八大基本类型

“byte和short两兄弟去找int问long去哪了” “int摇摇头说不知道” “此时float和double两兄弟也来凑热闹” “共同商议后决定去找char询问” “char面对五人的询问只好说boolean知道” “六人来到boolean的住处发现long竟然在玩猜真假游戏” Java语言的特点 1.简单易学…

个性化学习路径推荐综述

源自&#xff1a;软件学报 作者&#xff1a;云岳 代欢 张育培 尚学群 李战怀 摘 要 近年来, 伴随着现代信息技术的迅猛发展, 以人工智能为代表的新兴技术在教育领域得到了广泛应用, 引发了学习理念和方式的深刻变革. 在这种大背景下, 在线学习超越了时空的限制,…

2023年电信推出新套餐:月租19元=135G流量+长期套餐+无合约期!

在三大运营商推出的流量卡当中&#xff0c;电信可以说是性价比最高的一个&#xff0c;相对于其他两家运营商&#xff0c;完全符合我们低月租&#xff0c;大流量的要求&#xff0c;所以&#xff0c;今天小编介绍的还是电信流量卡。 在这里说一下&#xff0c;小编推荐的卡都是免…

教你怎样用PXE高效的批量网络装机

目录 一&#xff1a;PXE介绍 1.XPE概述 2.PXE批量部署的优点 3.搭建PXE各部作用 &#xff08;1&#xff09;PXE(Preboot eXcution Environment) &#xff08;2&#xff09;服务端 &#xff08;3&#xff09;客户端 二&#xff1a;部署PXE服务 1.安装并启用TFTP服务 2.安…

Tiktok/抖音旋转验证码

声明 本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 如有侵权,请联系我进行删除。 抖音系的旋转验证码,跟得物一样,都是内外圈一起…

blast的-max_target_seqs?

Shah, N., Nute, M.G., Warnow, T., and Pop, M. (2018). Misunderstood parameter of NCBI BLAST impacts the correctness of bioinformatics workflows. Bioinformatics. 杂志Bioinformatics以letter to the editor的形式刊发了来自美国马里兰大学计算机系的Nidhi Shah等人…

基于html+css的图展示42

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

安卓设备远程管理软件

现在&#xff0c;安卓设备广泛应用于各类智能硬件&#xff0c;有时候我们需要远程管理这些安卓设备。远程管理软件使 IT 管理员能够从任何地方控制和管理安卓设备&#xff0c;确保它们安全、最新并以最佳水平运行。在本文中&#xff0c;我们将介绍一些当前主流的安卓设备远程管…

Automa函数学习(三)

从变量中获取数据 当我们想要用automa获取文本标签获取到网页的文本内容后,想要将获取到的文本内容当做参数往后面的标签里进行传递时就需要用到automa提供的传参格式 {{ variables.自定义参数名}} 举例: 先建立打开百度首页工作流 前面自定义的变量名为text,所以这里参数拼接…