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

news2024/11/24 9:29:36

 为什么这道题的难度是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.coloradmin.cn/o/754463.html

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

相关文章

ffmpeg2段视频合成一段

查看分辨率 帧率和编码器 ffprobe -v error -select_streams v:0 -show_entries streamcodec_name,width,height,avg_frame_rate -of defaultnoprint_wrappers1 rs2.mp4得到&#xff0c;编码器&#xff0c;分辨率&#xff0c;还有帧率 codec_nameh264 width1920 height1080 avg…

小白到运维工程师自学之路 第五十二集 (三剑客之awk)

一、概述 awk命令是一种在Unix或类Unix系统上使用的文本处理工具。它以行为单位读取输入文件&#xff0c;按照预定义规则对每一行进行处理并生成输出。 通过使用一种简单的编程语言&#xff0c;awk提供了对文本数据进行过滤、处理和转换的强大能力。它可以轻松地提取文本中的…

实验四 交换机 VLAN 配置

文章目录 实验目的实验原理实验内容实验总结 实验目的 理解 VLAN 的概念、原理&#xff1b;掌握基于交换机端口的 VLAN 划分方法&#xff1b;掌握 Cisco2950 交换机的单交换机和跨交换机 VLAN 配置方法。 实验原理 &#xff08;1&#xff09;VLAN 的概念 VLAN&#xff08;Vi…

CQ 社区版 2.2.0 发布 | 配置要求降为 4 核 16G!!!

&#x1f389;&#x1f389;&#x1f389; 喜大普奔&#xff01;&#xff01;&#xff01; 经过我们研发团队的不断努力&#xff0c;CloudQuery 终于「瘦身」成功啦&#xff01;&#xff01;&#xff01; 本次发布的 v2.2.0 版本&#xff0c;推荐配置降为&#xff1a; CPU&a…

【iOS内存管理-内存的几大区域】

前言 iOS内存管理的第一篇章&#xff0c;了解iOS内存的五大分区。 总览 iOS中&#xff0c;内存主要分为五大区域&#xff1a;栈区&#xff0c;堆区&#xff0c;全局区/静态区&#xff0c;常量区和代码区。总览图如下。 如上图所示&#xff0c;代码区是在低地址段存放&#x…

关于AWS MSK Connector Execution Role的解释

尽管在创建AWS MSK Connector时&#xff0c;Execution Role是一个必填项&#xff0c;就像下面这样&#xff1a; 并且在官方文档中给出的Execution Role样例&#xff1a; https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-service-execution-role.html 中也…

基于JSP+Servlet的学生信息管理系统

用户类型&#xff1a;三角色&#xff08;学生、教师、管理员&#xff09; 项目架构&#xff1a;B/S架构 设计思想&#xff1a;MVC 开发语言&#xff1a;Java语言 前端技术&#xff1a;Layui、HTML、CSS、JS、JQuery、Ajax等技术 后端技术&#xff1a;JSP、Servlet、JDBC、…

基于JSP+Servlet的医药药品管理系统

用户类型&#xff1a;双角色角色&#xff08;患者、管理员[医生]&#xff09; 设计模式&#xff1a;MVC&#xff08;jspservletjavabean) 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 主要技术&#xff1a;jsp、servlet、jdbc、jsp、html5、jquery、css、js…

【哈希表/字符串-简单】LeetCode 205 同构字符串 Java

需要判断s和t每个位置上的字符是否都一一对应&#xff0c;即s的任意一个字符被t中唯一的字符对应&#xff0c;同时t的任意一个字符被s中唯一的字符对应。这也被称为【双射】的关系。 以示例二为例&#xff0c;t中的字符a和r虽然有唯一的映射o&#xff0c;但对于s中的字符o来说…

Vim批量注释与反注释

在使用vim编写代码的时候&#xff0c;经常需要用到批量注释与反注释一段代码。下面简要介绍其操作。本文记录在mac/linux下的vim批量注释。 一开始我想让vim配置ctrl/快捷键&#xff0c;快速批量注释&#xff0c;但是vim的文档中不支持这样的快捷键。 如果实在要弄也能弄&…

集群基础2——LVS负载均衡httpd服务(nat模式)

文章目录 一、环境说明一、配置调度器网卡二、配置后端服务器三、配置调度器四、验证五、设置https负载均衡 一、环境说明 使用lvs中的nat模型&#xff0c;对http负载均衡集群。 主机IP角色安装服务真实IP&#xff1a;192.168.161.129VIP&#xff1a;192.168.161.130调度服务器…

深信服 网络工程师面试题(二)

指针函数和函数指针的区别 指针函数是指带指针的函数&#xff0c;即本质是一个函数&#xff0c;函数返回类型是某一类型的指针。 首先它是一个函数&#xff0c;只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受&#xff0c;也就是说&#xff0c;指…

牛客HJ99 - 自守数【暴力 + 换位取模】

原题传送门 原题描述 首先我们来看一下原题是怎么描述的&#xff0c;题面很简单&#xff0c;输入n&#xff0c;然后让我们去统计从1 ~ n之间的自守数有几个&#xff0c;那什么是【自守数】呢&#xff0c;上面也说到了&#xff0c;即一个数在平方之后该数的尾数等于该数自身的自…

榜单!高精定位模块/系统「争夺战」,份额Top5供应商都有谁

以当前国内车企落地高速NOA采用的主流方案为例&#xff0c;普遍采用了「高精定位高精地图车端传感器」的多源融合定位策略。其中&#xff0c;在高精定位部分&#xff0c;大部分采用GNSSIMURTK的方案。 从目前的智驾系统演进来看&#xff0c;主流的仍是在L2基础上&#xff0c;通…

k8s 基础命令和常用命令等

通过kubectl命令可以操作和管理K8S资源&#xff0c;对于初学者可以在掌握K8S基础命令的基础上再去学习K8s的原理和架构&#xff0c;那么K8S常用的命令有哪些呢&#xff1f; 01 K8S命令概述 在学习K8s基础命令前&#xff0c;了解和学习docker命令是很有必要的&#xff0c;kub…

c语言--unsigned修饰符

在C语言中&#xff0c;unsigned是一种无符号整数修饰符。它可以与多个整数类型&#xff08;如int、short、long等&#xff09;结合使用&#xff0c;表示该整数类型只包含非负数值。unsigned修饰的整数类型不保存正负号位&#xff0c;因此可以用来表示更大的正整数范围。 例如&…

干货分享|SOLIDWORKS Composer如何解决缺失的actor?

​SOLIDWORKS Composer导入SOLIDWORKS模型&#xff0c;以便用户可以创建图形内容并与更广泛的受众共享项目。但是&#xff0c;有时模型导入时缺少Actor或组件&#xff0c;通常是由于在SOLIDWORKS中以轻量模式加载组件或Composer中的导入设置排除了曲面实体。 轻量模式 轻量模式…

基于DEF生成LIB的方法

基于DEF生成LIB的方法 [生成64位lib] lib /def:libcurl-x64.def /MACHINE:x64 /OUT:libcurl-x64.lib[生成32位lib] lib /def:libcurl-x64.def /OUT:libcurl-x64.lib

flutter开发实战-生日等日期选择器DatePicker

flutter开发实战-生日等日期选择器DatePicker 在开发遇到设置生日等信息需要选择日期&#xff0c;这里用到的是CupertinoDatePicker iOS效果的日期、时间选择器 一、效果图 运行后效果图如下 二、代码实现 我们需要调用底部弹窗显示 //显示底部弹窗static void bottomShe…

07_flash全擦除实验

07_flash全擦除实验 1. SPI 协议1.1 SPI 协议1.2 SPI 物理层1.3 SPI 协议层1.3.1 SPI 通讯模式时序图1.3.2 CPHA0 时的 SPI 通讯模式1.3.3 CPHA1 时的 SPI 通讯模式 2. 实验目标3. SPI-Flash 芯片3.1 硬件资源3.2 板载 Flash 原理图3.3 操作时序3.3.1 全擦除时序3.3.2 写使能时…