求解二叉树中两个结点的最低公共父结点

简介:

一,问题描述

构建一棵二叉树(不一定是二叉查找树),求出该二叉树中某两个结点的最低公共父结点。借用一张图如下:

Binary Tree

结点8 和 结点5 的最低公共父结点为 结点2

 

二,二叉树的构建

与 求二叉树中第K层结点的个数 文章中的第二点:二叉树构建相同

 

三,求解最低公共父结点的算法实现

有两种思路,一种是通过中序遍历和后序遍历。由于中序遍历是先左子树中的结点,再访问根,再访问右子树中结点,因此这两个结点的公共父结点一定处于这两个结点之间。

如:中序遍历:8, 4, 9, 2, 5, 1, 6, 3, 7     结点2处于结点8 和 结点5 之间,也就是说:结点8 和 结点5 的最低公共父结点在 [8~5]之间的候选结点,这里为{4,9,2}中取

后序遍历是先访问左右子树中的结点,最后再访问根。故这两个结点的最低公共父结点一定处于 结点8 和 结点5 之后的结点,且是第一个出现在{4,9,2}中的那个结点。

后序遍历:8, 9, 4, 5, 2, 6, 7, 3, 1        8->9->4->5 这之后的结点,才可能是 结点8 和 结点5 的父结点。

 

另一种方法则是:递归,首先从树根开始考虑:

①结点A 和 结点B 要么都在树根的左子树中;②要么都在树根的右子树中;③要么一个在左子树中,一个在右子树中。

这是一个分治算法,对于情况①和②,可以继续递归分解。对于情况③属于代码第10行判断,复杂度为O(1)

递归表达式可表示为:T(N)=2T(N/2)+O(1),解得T(N)=O(N)

对于③,最低公共父结点为树根。

对于①,可以进一步判断,从树根的左孩子结点考虑:

1)结点A 和 结点B 要么都在树根的左子孩子 的 左子树中;2)要么都在树根的左孩子 的 右子树中;3) 要么一个在树根的左孩子的 左子树中,一个在树根的左孩子 的 右子树中。

对于②,可以进一步判断,从树根的右孩子的结点考虑:

1)结点A 和 结点B 要么都在树根的右子孩子 的 左子树中;2)要么都在树根的右孩子 的 右子树中;3) 要么一个在树根的右孩子的 左子树中,一个在树根的右孩子 的 右子树中。

下面代码实现递归求解最低公共父结点。

 

四,代码实现(node1 node2 都是二叉树中的结点)

复制代码
 1     /**
 2      * 求解node1 和 node2 的最低公共父结点
 3      * @param node1
 4      * @param node2
 5      * @return 最低公共父结点
 6      */
 7     public BinaryNode<T> commonNode(BinaryNode<T> node1, BinaryNode<T> node2, BinaryNode<T> root){
 8         if(root == null)
 9             return null;
10         if(node1.element == root.element || node2.element == root.element)
11             return root;
12         /*
13          * 若 left==null, node1,node2 都不在 root.left子树中
14          * 若right==null,node1,node2 都不在root.right子树中
15          */
16         BinaryNode<T> left = commonNode(node1, node2, root.left);
17         BinaryNode<T> right = commonNode(node1, node2, root.right);
18         
19         if(left != null && right != null)
20             return root;
21         return left == null ? right : left;
22     }
复制代码

根据程序中的第8行和第10行的if语句,可知:

1)若 left==null, 则说明 node1,node2 都不在 root.left子树中

2)若right==null,则说明 node1,node2 都不在root.right子树中

 

3)当对于某个结点,当执行了第16,17行的递归后 ,left 和 right 都不为空,说明node1 在 该结点.left子树中,node2 在 该结点.right子树中

故第19-20行,返回 该结点 作为公共父结点

例如,求结点8 和 结点5 的最低公共父结点:递归调用过程如下:

a)commNode(8,5,1)==2

b1)      commNode(8,5,2)==2

c1)             commNode(8,5,4)==8

d1)                      commNode(8,5,8)==8

d2)                      commNode(8,5,9)==null

c2)             commNode(8,5,5)==5

b2)      commNode(8,5,3)==null

 

a)生成了 b1)  b2) 两个递归调用,其中 b2)为空,因为结点8,结点5 不在以3为根的子树中

b1)生成了 c1)   c2)两个递归调用,其中 c2) 是commNode(8,5,5),根据程序第10行if,返回5,而c1)又生成了 d1)  d2)两个递归调用

其中,d1) 返回8,d2)返回null, 故执行到第21行语句,return 不空的那个left/right,也就是 d1) 返回的结点8

 

由于 c1)返回了5, c2)返回了8,都不为空,执行到第19-20行,返回它们的root,即,结点4和结点5的公共父结点:结点2

由于 b1) 生成了 c1)  c2)   故 b1) 的值是结点2    又因为 b2) 为null

故 a) 最终是 b1) 的值,即为结点2

可把该方法放到求二叉树中第K层结点的个数 中 的完整代码给出的程序中进行测试。

 

五,参考资料

How to find the lowest common ancestor of two nodes in any binary tree?


本文转自hapjin博客园博客,原文链接:http://www.cnblogs.com/hapjin/p/5508284.html,如需转载请自行联系原作者

相关文章
|
8月前
|
SQL 存储 关系型数据库
MySQL秘籍之索引与查询优化实战指南
最左前缀原则。不冗余原则。最大选择性原则。所谓前缀索引,说白了就是对文本的前几个字符建立索引(具体是几个字符在建立索引时去指定),比如以产品名称的前 10 位来建索引,这样建立起来的索引更小,查询效率更快!
284 22
 MySQL秘籍之索引与查询优化实战指南
|
9月前
|
人工智能 编解码 机器人
NVILA:英伟达开源视觉语言大模型,高效处理高分辨率图像和长视频
NVILA是英伟达推出的视觉语言大模型,旨在高效处理高分辨率图像和长视频,同时保持高准确性。该模型通过“扩展-压缩”策略和多种优化技术,在多个领域如机器人导航和医疗成像中展现出广泛的应用潜力。
332 13
NVILA:英伟达开源视觉语言大模型,高效处理高分辨率图像和长视频
|
9月前
|
编解码 算法 API
国产多通道肌电采集芯片及肌电模块
唯理WLEC3医疗级肌电模块,采用自研WLM128芯片,具备低功耗、高精度特点,适用于肌电采集及手势识别等应用。模块内置滤波、降噪算法,支持蓝牙/串口数据传输,兼容多种通道配置,提供云端API深度分析,确保高效精准的数据处理。
|
11月前
|
机器学习/深度学习 运维 监控
深度学习之视频内容理解
基于深度学习的视频内容理解(Video Content Understanding, VCU)是一项关键技术,旨在通过神经网络模型自动分析、解读和提取视频中的语义信息。
670 10
|
存储 SQL Oracle
什么是 RDBMS?
【8月更文挑战第1天】
358 6
什么是 RDBMS?
|
XML 缓存 前端开发
别用 Filter 了,试试 Spring 自带的方式处理 CORS 跨域问题
从 CORS 到 Spring MVC 跨源资源共享(CORS) 即 Cross-Origin Resource Sharing,也常被译为跨域资源共享。作为 W3C 的标准,它允许浏览器向跨源服务器发起请求,克服了 AJAX 只能同源使用的限制。
699 0
别用 Filter 了,试试 Spring 自带的方式处理 CORS 跨域问题
|
存储 机器学习/深度学习 人工智能
5个优质免费自然语言处理学习资源 | 语言技术导航
5个优质免费自然语言处理学习资源 | 语言技术导航
|
安全 测试技术 数据库
软件测试案例 | 某教务管理平台系统的系统测试总结报告
集成测试通过之后,各个模块已经被组装成了一个完整的软件包,这时就需要进行系统测试了。传统的系统测试指的是通过集成测试的软件系统,作为计算机系统的一个重要组成部分,其将与计算机硬件、外部设备、支撑软件等其他系统元素组合在一起进行测试,目的在于通过与系统需求定义作比较,发现软件与需求规格不符合或者相矛盾的地方,从而提出更加完善的解决方案。这里特别提出需要软硬件支撑的虚拟现实(Virtual Reality,VR)项目测试的特殊性。
831 0
软件测试案例 | 某教务管理平台系统的系统测试总结报告
|
SQL Java 数据库连接
Java【付诸实践 01】使用org.apache.ibatis.plugin.Interceptor拦截器实现全局mapper.xml参数注入(可用于切换数据库实例schema)源码实例分享
Java【付诸实践 01】使用org.apache.ibatis.plugin.Interceptor拦截器实现全局mapper.xml参数注入(可用于切换数据库实例schema)源码实例分享
427 0
|
存储 Unix Linux
Windows下文件创建时间竟然比修改时间晚!!!linux&&windows 文件系统的认识
windows下文件创建时间晚于修改时间的猫腻:文件移动目录会改变创建时间。
1401 1