热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

二叉树的最近公共祖先并不简单

某一天中午吃饭的时候,一同事问我:怎么找二叉树的最近公共祖先。我起初以为这是一道青铜题,真正了解题意后,发现这是一道王者题。给一棵树,以及树上的两个节点指针。

一、背景

某一天中午吃饭的时候,一同事问我:怎么找二叉树的最近公共祖先。

我起初以为这是一道青铜题,真正了解题意后,发现这是一道王者题。

二、题意

给一棵树,以及树上的两个节点指针。

求这两个节点在树上的最近公共祖先。

如下图,

节点 7 和节点 0 的最近公共祖先是节点 3

节点 4 和节点 6 的最近公共祖先是节点 5

二叉树的最近公共祖先并不简单

那该如何实现一个算法,找到两个节点的最近公共祖先呢?

三、链表相交思想

同时问我这个问题的时候,我首先想到的是链表相交,求第一个交点的算法思想。

如果每个节点有指向父节点的指针的话,我们就可以把给的两个节点当做链表头,树的根是链表尾部。

这样问题就转化为了求两个相交链表的第一个交点。

对应的思想是先遍历两个链表分别求出两个链表的长度。

然后对其长度,使得两个节点处于树的同一层。

最后同时向上遍历,判断是不是同一个节点,试了就找到交点了。

但是题目给的是一个普通的二叉树,没有父节点指针,所以就需要想其他方法了。

四、初级递归

面对树的问题,很容易想到递归处理。

同样,这个题也可以使用递归处理。

思路大概是:

  1. 先判断公共祖先是否在左子树,是则找到
  2. 再判断公共祖先是否在右子树,是则找到
  3. 当前根是不是公共祖先,是则找到
  4. 当前树没有公共祖先

这里有一个关键问题:怎么判断当前根是不是公共祖先呢?

这个貌似又是一个递归题,可以拆解为根是不是节点 A 的祖先和根是不是节点 B 的祖先。

两个同时满足了,根就是这两个节点的公共祖先。

这样这道题我们就做出来了,但是复杂度貌似有点高。

对于每个子树,都进行了判断根是不是祖先,这样就相当于双层循环,复杂度是 O(n^2)

二叉树的最近公共祖先并不简单

所以我们需要继续思考,有没有更简单的方法。

五、高级递归

其实,在初级递归的时候,复杂度之所高,就是需要在每个子树里判断一个根是不是两个节点的祖先。

这个判断在每个子树里是独立的,但是实际上树与树之间是有关系的。

比如当前树的左儿子是节点 A 的祖先,那当前树的根肯定也是节点 A 的祖先。

递归的时候,如果能服用这个信息,则可以将复杂度降低到 O(n)

二叉树的最近公共祖先并不简单

上面的递归代码需要返回三个值。

最近公共祖先通过返回值返回,没找到则返回 NULL

两个节点是否找到使用参数引用的方式返回。

然后用下面的代码来判断,某个节点是否在当前子树里。

  1. 是否等于根
  2. 是否在左子树
  3. 是否在右子树
pCncestor = p == root || leftPCncestor || rightPCncestor; //if find p in root
qCncestor = q == root || leftQCncestor || rightQCncestor; //if find q in root

这样,这个道题我们就可以在 O(N) 内解决了。

当然,当时同事网上看的解题源码不是这种思想。

而是一种比较抽象的方法:只有一个返回值,含义是当前子树是否至少含一个节点。

这是一个返回值在不同的条件下含义是不同的。

如下图,如果根和某个节点相同,则返回根。

这里隐含两个含义:

1.如果两个节点都在这颗树里,根是其中一个节点,答案是根。

2.如果只有一个节点在这颗树里,那只能是根了,返回根代表找到了至少一个节点。

然后递归求出连个子树的状态,如果分别都找到一个节点,则代表根是节点。

否则说明这棵树只有一个节点,是谁就返回谁。

二叉树的最近公共祖先并不简单

六、最后

这道题其实还蛮有难度的,一个递归需要返回多种状态。

状态一多,很多人就弄不明白了。

-EOF-


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • c# java socketn 字节流_C#Socket编程详解(一)TCP与UDP简介
    一、TCP与UDP(转载)1、TCP1.1定义TCP(TransmissionControlProtocol)传输控制协议。是一种可靠的、面向连接的协议(eg:打电话)、传输效率低 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • PHP组合工具以及开发所需的工具
    本文介绍了PHP开发中常用的组合工具和开发所需的工具。对于数据分析软件,包括Excel、hihidata、SPSS、SAS、MARLAB、Eview以及各种BI与报表工具等。同时还介绍了PHP开发所需的PHP MySQL Apache集成环境,包括推荐的AppServ等版本。 ... [详细]
  • 远程桌面同步本地计算机,微软更新远程桌面应用现在终于可以在本地和远程计算机上复制文件...
    远程桌面连接是许多专业用户和开发者必备的功能,通过远程桌面服务可以直接连接远程计算机并可以直接操作。系统自带的远程桌面连接程序微软已经很久没有更新,因为 ... [详细]
  • Linux一键安装web环境全攻略
    摘自阿里云服务器官网,此处一键安装包下载:点此下载安装须知1、此安装包可在阿里云所有Linux系统上部署安装,此安装包包含的软件及版本为& ... [详细]
  • 计算机网络计算机网络分层结构
    为了解决计算机网络复杂的问题,提出了计算机网络分层结构。计算机网络分层结构主要有OSI7层参考模型,TCPIP4层参考模型两种。为什么要分层不同产商 ... [详细]
  • ***Createdbyjiachenpanon161118.**合法uri*exportfunctionvalidateURL(textval){consturlregex^( ... [详细]
  • 网络安全是一个非常重要的课题,基本上你运行的服务后台越多,你就可能打开更多的安全漏洞.如果配置的恰当的话,Linux本身是非常安全可靠的,假使在Linux系统中有某个安全缺陷,由于Linu ... [详细]
  • HTTP协议相关的网络经典五层模型
    网络通信相关概念的讲解–网络协议分层(经典五层模型)在我们了解HTTP相关内容之前我们先来了解一下“网络协议分层”相关内容,因为这个是我们了解HTTP相关内容的前提条件;大家有一 ... [详细]
  • 0x00端口渗透端口扫描端口的指纹信息(版本信息)端口所对应运行的服务常见的默认端口号.尝试弱口令端口爆破hydra端口弱口令NTScanHs ... [详细]
  • 本人新手,用Unity3D想做一个简单的赛车游戏,现在的问题是转弯的时候很容易出现翻车的情况,求解决思路比如说你的中心是在(0,0,0),你把他设置成(0,-1.0,0)之类的就可 ... [详细]
  • javaftp上传,javaftp下载文件
    本文目录一览:1、javaftp上传5G以上大文件,怎么做 ... [详细]
  • linux下的mesa一般版本比较低,按照高版本mesa1.下载代码下载路径:https:www.mesa3d.org用git下载容易失败。用Downl ... [详细]
  • IP双栈环境下网络应用迁移
    IPv4向IPv6迁移有多种途径,在选择具体的迁移方式时,当前环境中运行的应用是否支持IPv6是重要的考量因素之一,同时在编写新的应用时,需要考虑新编写的应用不仅可以适应当前主流的IPv4环境, ... [详细]
  • 苹果mac休眠快捷键_哪里不会点哪里苹果电脑应用手册
    找到所需内容,点击链接查看视频教程一、系统设置1.1用户密码的设定与使用用户密码的设定与更改1.2添加输入法鼠标触控板快捷键屏幕录像输入法鼠标触控板快捷键屏幕录像1. ... [详细]
author-avatar
葉_沛峰
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有