热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

二叉树--最近公共父节点

给定二叉树中的任意两点,求解该两点的最近公共父节点。程序大致分为递归和非递归两种方式,下面我们先来认识非递归的方式。非递归程序总体的思路:用一种常见高效的数据结构来记录下二叉树中的结

给定二叉树中的任意两点,求解该两点的最近公共父节点。程序大致分为递归和非递归两种方式,下面我们先来认识非递归的方式。

非递归

程序总体的思路:用一种常见高效的数据结构来记录下二叉树中的结构关系,由于是找父节点,所以要用子节点来查找父节点,我们这里用到的是HashMap来进行树形关系的存储。接下来就是先列出一个要求节点的所有父节点,然后比较另一个要求节点的父节点在不在上面的列中,第一个出现的节点,就是我们要求的祖先节点。具体代码如下:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    Map<TreeNode, TreeNode> parent = new HashMap<>();//存储关系
    Queue<TreeNode> queue = new LinkedList<>();//辅助队列
    parent.put(root, null);
    queue.add(root);
    while (!parent.containsKey(p) || !parent.containsKey(q)) {
        TreeNode node = queue.poll();
        if (node != null) {
            parent.put(node.left, node);
            parent.put(node.right, node);
            queue.add(node.left);
            queue.add(node.right);
        }
    }
    Set<TreeNode> set = new HashSet<>();//p节点的所有祖先节点
    while (p != null) {
        set.add(p);
        p = parent.get(p);
    }
    while (!set.contains(q)) {//第一个出现的节点,就是return
        q = parent.get(q);
    }
    return q;
}

下面来看递归求解过程(只需要抓住一点,两个节点要么在左子树上,要么在右子树上,root就更简单了):

// recursively
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null || root == p || root == q) {
        return root;
    }
    TreeNode l = lowestCommonAncestor(root.left, p, q);
    TreeNode r = lowestCommonAncestor(root.right, p, q);
    return l != null && r != null?root : l == null?r: l;
}

这个代码写的也是没谁了,尤其是最后的return,只能膜拜一下了,解释一下最后的一句返回:首先,判断左右子树,如果有空,则返回左子树,原因是在递归程序中,先求解的左子树的节点;如果左右都不为空,则返回他们的父节点,则这个节点,就应该是结果;后面又加了一个三目运算符,原因是,上面返回的左子树有可能为null,比如两个节点都在root的右子树上,那么当左子树为空时,则返回右子树;


推荐阅读
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 单线程化的ConcurrentHashMap的性能要比同步的HashMap的性能稍好一些,而且在并发应用中,这种作用就十分明显了。ConcurrentHashMap的实现,假定大多数常用的操 ... [详细]
  • 转载自:http:www.blogjava.netCarpenterLeearchive20160427430268.html总体介绍之所以把HashSet和HashMa ... [详细]
  • 在Ubuntu上安装MySQL时解决缺少libaio.so.1错误及libaio在MySQL中的重要性分析
    在Ubuntu系统上安装MySQL时,遇到了缺少libaio.so.1的错误。本文详细介绍了如何解决这一问题,并深入探讨了libaio库在MySQL性能优化中的重要作用。对于初学者而言,理解这些依赖关系和配置步骤是成功安装和运行MySQL的关键。通过本文的指导,读者可以顺利解决相关问题,并更好地掌握MySQL在Linux环境下的部署与管理。 ... [详细]
  • 缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • Java学习第10天:深入理解Map接口及其应用 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • 深入解析 Android TextView 中 getImeActionLabel() 方法的使用与代码示例 ... [详细]
  • 如何使用 com.jme3.input.FlyByCamera 构造函数及其代码示例详解 ... [详细]
author-avatar
亚S哥_271
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有