剑指oferr68-II.二叉树的最近公共祖先

 为什么这道题的难度是easy,我感觉挺难的啊,我想了挺久没有一点思路就直接看题解了。题解有两种解法,先看第一种存储父节点

class Solution {
    Map<Integer,TreeNode> parent = new HashMap<Integer,TreeNode>();
    Set<Integer> visited = new HashSet<Integer>();
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root);
        while(p != null){
            visited.add(p.val);
            p = parent.get(p.val);
        }
        while(q != null){
            if(visited.contains(q.val))return q;
            q = parent.get(q.val);
        }
        return null;
    }


    private void dfs(TreeNode root){
        if(root.left != null){
            parent.put(root.left.val, root);
            dfs(root.left);
        }
        if(root.right != null){
            parent.put(root.right.val, root);
            dfs(root.right);
        }
    }

}

它是用一个parent的HashMap来存储所有节点的父节点,HashMap键值对的类型是<Integer,TreeNode>,Integer是子节点的值,TreeNode是父节点的引用,然后利用parent.get(p.val)的方法获得p的父节点,然后把父节点的值放入一个叫visited的set里面,然后

p = parent.get(p.val),p就变成了他的父节点,在循环一次就把,p的爷爷节点的值放进了set,

对于q而言,就直接看set里面有没有q.val,如果有说明q是p的祖宗,直接返回q就可以,如果没有,q就变成他的父节点,再看set里面有没有,这样一直循环就会找到p和q的最近祖先。

还有一种方法是递归。

class Solution {
    private TreeNode ans;
    public Solution(){
        this.ans = null;
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
       dfs(root, p, q);
       return this.ans;
    }
    
    private boolean dfs(TreeNode root, TreeNode p, TreeNode q){
        if(root == null) return false;
        boolean lson = dfs(root.left, p, q);
        boolean rson = dfs(root.right, p, q);
        if((lson && rson) || ((root.val == p.val || root.val == q.val) && (lson || rson))){
            ans = root;
        }
        return lson || rson || (root.val == p.val) || (root.val == q.val);
    }
}

 如果x是p,q的最近公共祖先,那么{x的左子树包含p右子树包含q(左子树包含q右子树包含p)}或者{[x是p x的左子树包含q(右子树包含p)] [x是q x的左子树包含p(x的右子树包含p)]},x只存在大括号这两种情况。因为如果x是最近公共祖先的话,x的一颗子树上不可能同时存在p和q(如果同时存在,那么最近的公共祖先不是x而是x的子孙)这个解释的是第一个大括号,如果x是p的话,那么q一定在x的左子树或者右子树上  解释的是第二个大括号。逻辑搞清楚了,接下来看代码,dfs采用的是左右根的遍历方式。dfs可以看作是自下而上用来标记每个子树是true还是false的方法,如果它的值等于p或q那么他就是true,或者他的左子树或者右子树是true那么他就是true,并且在遍历的同时还会判断这个节点是不是最近公共祖先,判断的方法就是刚才讲的大括号的两种情况,因为是自下而上的,所以最先找到的公共祖先就是最近公共祖先,当找到了这个最近公共祖先后,它也被设置成了true,但是他的兄弟不可能是true,因为pq都在x这边,这样的话对于x的父节点,根据判断条件,flson&&frson是fasle,第二种情况也是false,也就是说x的父节点不可能是最近公共祖先,但是它被标记为了true,但是x的父节点的兄弟不可能是true,因为pq都在x的父节点这边,以此类推可以得出,x的兄弟节点和他的祖先节点都不会变成最近公共祖先。

这个方法逻辑性太强了,我理了半个多小时才把这个逻辑搞清楚,不如方法一容易理解,但是确实很巧妙。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】Burpsuite v2021.12.1安装激活配置快捷启动

Burpsuite v2021.12.1安装&激活&配置&快捷启动 一、下载激活包二、配置JDK11三、启动激活 一、下载激活包 需要下载的内容&#xff1a; Burp Suite jar包JDK11激活jar包汉化jar包 下面是已经下载好的&#xff0c;可以直接使用 BurpSuite网盘下载链接 提取码&#…

【运维】第03讲(上):Nginx 负载均衡常见架构及问题解析

实际上 Nginx 除了承担代理网关角色外还会应用于 7 层应用上的负载均衡&#xff0c;本课时重点讲解 Nginx 的负载均衡应用架构&#xff0c;及最常见的问题。 学前提示 Nginx 作为负载均衡是基于代理模式的基础之上&#xff0c;所以在学习本课时前&#xff0c;你需要对 Nginx …

本地appserv外挂网址如何让外网访问?快解析端口映射

一、appserv是什么&#xff1f; AppServ 是 PHP 网页架站工具组合包&#xff0c;作者将一些网络上免费的架站资源重新包装成单一的安装程序&#xff0c;以方便初学者快速完成架站&#xff0c;AppServ 所包含的软件有&#xff1a;Apache[、Apache Monitor、PHP、MySQL、phpMyAdm…

JavaFX中MVC例子理解

JavaFX可以让你使用GUI组件创建桌面应用程序。一个GUI应用程序执行三个任务&#xff1a;接受用户的输入&#xff0c;处理输入&#xff0c;并显示输出。而一个GUI应用程序包含两个 类型的代码&#xff1a; 领域代码。处理特定领域的数据和遵循业务规范。交互代码。处理用户输入…

Elasticsearch:使用 Elasticsearch 矢量搜索和 FastAPI 构建文本搜索应用程序

在我的文章 “Elastic&#xff1a;开发者上手指南” 的 “NLP - 自然语言处理及矢量搜索”&#xff0c;我对 Elastic Stack 所提供的矢量搜索有大量的描述。其中很多的方法需要使用到 huggingface.co 及 Elastic 的机器学习。这个对于许多的开发者来说&#xff0c;意味着付费使…

【Linux】进程优先级

Linux 进程优先级 为什么要有优先级的划分&#xff1f;Linux 环境设置优先级的具体做法并发运行环境变量如何通过代码获取环境变量 环境变量的来源 为什么要有优先级的划分&#xff1f; 优先级的规定就是为了确定某种资源获取的先后顺序。 本质原因是因为CPU资源是有限的。进程…

KMP算法

KMP KMP 算法是一个快速查找匹配串的算法&#xff0c;它的作用其实就是本题问题&#xff1a;如何快速在「原字符串」中找到「匹配字符串」。 而 KMP 算法的复杂度为 O(mn)实际上是O(N),因为O(M)不可能大于O(N) KMP 之所以能够在 O(mn)复杂度内完成查找&#xff0c;是因为其能…

CentOS环境下的MYSQL8安装

MySQL 安装 参考连接&#xff1a;https://www.cnblogs.com/jasonx1an/p/16690866.html 下载 下载网址&#xff1a;https://dev.mysql.com/downloads/mysql/ 卸载 mariadb 查看 mariadb rpm -qa|grep mariadb卸载 mariadb rpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps再…

概率栅格

欢迎访问我的博客首页。 概率栅格 1. miss 表与 hit 表 1. miss 表与 hit 表 miss 表和 his 表是一维数组&#xff0c;它们存放的都是空闲值。其下标 i i i 代表旧空闲值&#xff0c;元素 t a b l e [ i ] table[i] table[i] 代表旧空闲值 i i i 的新空闲值。表的更新可以用…

Maven —— 项目管理工具

前言 在这篇文章中&#xff0c;荔枝会介绍如何在项目工程中借助Maven的力量来开发&#xff0c;主要涉及Maven的下载安装、环境变量的配置、IDEA中的Maven的路径配置和信息修改以及通过Maven来快速构建项目。希望能对需要配置的小伙伴们有帮助哈哈哈哈~~~ 文章目录 前言 一、初…

安全防御 --- SSL VPN

附&#xff1a;无线项目介绍 SSL VPN 有浏览器的设备就可以使用SSL&#xff0c;进而使用SSL VPN。无需担心客户端问题&#xff0c;所以SSL VPN也称为无客户端VPN。SSL VPN在client to lan场景下特别有优势。 实际实现过程&#xff08;基于TCP实现&#xff09; &#xff08;1&…

MYSQL执行一条SELECT语句的具体流程

昨天CSDN突然抽风 我一个ctrlz把整篇文章给撤掉了还不能复原 直接心态崩了不想写了 不过这部分果然还是很重要,还是写出来吧 流程图 这里面总共有两层结构Server层 储存引擎 Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包…

Java-API简析_java.lang.ProcessBuilder类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131729933 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

什么是Docker

容器技术和虚拟机 虚拟机 和一个单纯的应用程序相比&#xff0c;操作系统是一个很重的程序&#xff0c;刚装好的系统还什么都没有部署&#xff0c;单纯的操作系统其磁盘占用至少几十G起步&#xff0c;内存要几个G起步。 在这台机器上开启三个虚拟机&#xff0c;每个虚拟机上…

Failed to connect to github.com port 443: Connection refused问题解决

文章目录 一、问题描述&#xff1a;Failed to connect to github.com port 443: Connection refused问题解决二、解决方法一&#xff1a;排查代理问题1、尝试重置代理或者取消代理的方式2、添加全局代理 三、解决方法二&#xff1a;排查DNS解析问题1、第一步&#xff1a;查找gi…

Redis解决Session共享问题

文章目录 一、集群Session共享问题二、Redis存储验证码和对象三、解决状态登录刷新问题 一、集群Session共享问题 session共享问题&#xff1a;多台Tomcat并不共享session存储空间&#xff0c;当请求切换到不同tomcat服务器时导致数据丢失的问题 tomcat可以进行多台tomcat进行…

蓝牙技术|低功耗蓝牙和LE Audio助力游戏设备行业发展

去年&#xff0c;蓝牙技术联盟官方宣布推出LE Audio&#xff0c;它以BLE为基础&#xff0c;旨在更好地兼顾音频质量和低功耗&#xff0c;以在多种潜在应用中显著增强用户体验。这在游戏行业中引起了轰动&#xff0c;由于其延迟显著降低&#xff0c;LE Audio在增强游戏体验方面展…

连接一个JavaScript文件

● 首先&#xff0c;本章我们会使用一个起始文件&#xff0c;代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0&qu…

unidbg或者java层解密方法IDEA中打包成jar包供python调用方法

一、导出jar包方法 &#xff08;1&#xff09;配置jar包参数 &#xff08;2&#xff09;创建生成jar包 成功生成&#xff01; 二、Python代码调用 import jpypejvmPath jpype.getDefaultJVMPath() d unidbg-android.jar # 对应jar地址 jpype.startJVM(jvmPath, "-ea&q…

apple pencil一代的平替有哪些品牌?苹果平板的触控笔

随着苹果Pencil系列的推出&#xff0c;平替电容笔在国内市场得到了较好的发展&#xff0c;随之的销量&#xff0c;也开始暴涨&#xff0c;苹果pencil因为价格太高&#xff0c;导致很多人买不起。目前市场上&#xff0c;有不少的平替电容笔&#xff0c;可以替代苹果的Pencil&…
最新文章