坚持刷题|二叉树的最近公共祖先

文章目录

  • 题目
  • 考察点
  • 代码实现
  • 实现总结
  • 为什么不用迭代的方法实现?
  • 二叉搜索树的最近公共祖先

Hello,大家好,我是阿月。坚持刷题,老年痴呆追不上我,今天刷:二叉树的最近公共祖先

题目

236.二叉树的最近公共祖先
在这里插入图片描述
在这里插入图片描述

考察点

  • 对二叉树的理解:理解二叉树的基本概念,包括节点、左右子树等。

  • 递归的理解和应用:解决这个问题的常用方法是使用递归。

  • 最近公共祖先的概念:理解最近公共祖先的概念,即两个节点在树中的最低公共祖先节点。

  • 时间复杂度和空间复杂度分析:能够分析算法的时间复杂度和空间复杂度,以及是否能够优化算法。

代码实现

public class LowestCommonAncestor {

    /**
     * 寻找二叉树中两个节点的最近公共祖先
     * @param root 二叉树的根节点
     * @param p 第一个节点
     * @param q 第二个节点
     * @return 最近公共祖先节点
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 如果根节点为空,或者根节点等于其中一个目标节点,直接返回根节点
        if (root == null || root == p || root == q) {
            return root;
        }

        // 在左子树中寻找目标节点
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        // 在右子树中寻找目标节点
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        // 如果左子树和右子树分别包含目标节点,说明当前节点为最近公共祖先
        if (left != null && right != null) {
            return root;
        }

        // 如果左子树包含目标节点,则返回左子树的结果
        // 如果右子树包含目标节点,则返回右子树的结果
        return left != null ? left : right;
    }

    public static void main(String[] args) {
        LowestCommonAncestor solution = new LowestCommonAncestor();

        // 创建一个二叉树
        TreeNode root = new TreeNode(3);
        root.left = new TreeNode(5);
        root.right = new TreeNode(1);
        root.left.left = new TreeNode(6);
        root.left.right = new TreeNode(2);
        root.right.left = new TreeNode(0);
        root.right.right = new TreeNode(8);
        root.left.right.left = new TreeNode(7);
        root.left.right.right = new TreeNode(4);

        TreeNode p = root.left;
        TreeNode q = root.right;

        TreeNode result = solution.lowestCommonAncestor(root, p, q);
        System.out.println("最近公共祖先: " + result.val);
    }
}

实现总结

  • 寻找二叉树的公共祖先,是一种自底向上的寻找,而二叉树的回溯过程就是自底向上。
  • 后序遍历(左右中)是天然的回溯过程,可以根据左右子树的返回值,来处理中节点的逻辑。
  • 递归
    • 递归函数返回值以及参数:
      • 返回值:递归函数返回的是最近公共祖先节点。
      • 参数:递归函数的参数包括当前节点 root,以及要查找的两个目标节点 p 和 q。
    • 终止条件:
      • 如果当前节点为空 (root == null),或者当前节点等于 p 或 q,则直接返回当前节点,因为当前节点就是其中一个目标节点的最近公共祖先。
    • 单层递归逻辑:
      • 在每一层递归中,首先向左子树和右子树递归查找目标节点 p 和 q。
      • 如果左子树和右子树都找到了目标节点,则当前节点就是最近公共祖先。
      • 如果只有左子树找到了目标节点,则返回左子树的结果。
      • 如果只有右子树找到了目标节点,则返回右子树的结果。
    • 在递归函数有返回值的情况下:
      • 如果要搜索一条边,递归函数返回值不为空的时候,立刻返回。
      • 如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
  • 时间复杂度:O(N)。
    • 对于每个节点,都要做一些固定的工作:检查它是否等于目标节点 p 或 q,然后向下递归左右子树。因此,时间复杂度可以表示为 O(N),其中 N 是二叉树中节点的数量。
    • 在最坏的情况下,需要遍历整个二叉树才能找到最近公共祖先节点。因此,时间复杂度是线性的,与二叉树中的节点数量成正比。

为什么不用迭代的方法实现?

迭代法不适合模拟回溯的过程。

  • 复杂性增加:在迭代法中,模拟回溯过程需要使用额外的数据结构,例如栈或队列,来跟踪节点的访问顺序。这增加了实现的复杂性,特别是在处理二叉树的情况下。
  • 代码可读性差:迭代法模拟回溯过程的代码可能会更加复杂,难以理解和调试。相比之下,递归的代码结构更为清晰,更容易表达出问题的解决思路。
  • 空间开销增加:迭代法在模拟回溯过程时可能需要消耗更多的内存空间,特别是对于大型树或搜索空间较大的情况下,栈的空间开销可能会非常高。
  • 性能问题*:在某些情况下,递归的实现可能比迭代的实现更有效率,因为递归天然地利用了函数调用栈,而不需要额外的数据结构来跟踪状态。

虽然迭代法可以实现回溯算法,但通常情况下,递归更适合模拟回溯过程,因为递归天然地具有树形结构,与树、图等数据结构的问题更为契合,实现起来更为简洁清晰。

二叉搜索树的最近公共祖先

坚持刷题|二叉搜索树的最近公共祖先

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

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

相关文章

JavaWeb后端开发(第一期):Maven基础、Maven的安装配置、如何创建maven项目模块、maven的生命周期

Java后端开发:2024年2月6日 -> LiuJinTao 文章目录 JavaWeb后端开发(第一期) : maven基础一、 maven介绍1.1 什么maven呢:1.2 maven的作用1.3 maven 模型1.4 maven 仓库 二、maven 安装2.1 配置本地仓库2.2 配置阿里…

设计模式-行为型模式(下)

1.访问者模式 访问者模式在实际开发中使用的非常少,因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差,可维护性变差,在没有特别必要的情况下,不建议使用访问者模式. 访问者模式(Visitor Pattern) 的原始定义是: 允许在运行时将一个或多个操作应用于一…

调和平均

L1-4 调和平均 分数 10 作者 陈越 单位 浙江大学 N 个正数的算数平均是这些数的和除以 N,它们的调和平均是它们倒数的算数平均的倒数。本题就请你计算给定的一系列正数的调和平均值。 输入格式&#xff1a…

Java学习-常用API(一)

Object类 Object类及其常用方法: 代码示例: Objects Objects类的引入,定义及其常见的方法: 示例 包装类 什么是包装类? 自动装箱和自动拆箱: 常用方法: 注意:字符串的 数值&#xf…

VS无法使用万能头文件#include <bits/stdc++.h> 的解决办法

第一步在vs中打出可以使用的头文件 如#include<cmath> 点击F12转到文档 上面窗口右键找到打开所在文件夹 创建一个名字为bits的文件夹 里面创建一个text文件 // C includes used for precompiling -*- C -*-// Copyright (C) 2003-2015 Free Software Foundation, In…

Java小区物业管理系统

技术架构&#xff1a; springboot mybatis thymeleaf Mysql5.7 有需要该项目的小伙伴可以私信我你的Q。 功能描述&#xff1a; 控制台、数据库、楼栋管理、单元管理、房屋管理、车位管理、缴费类型、缴费管理、公告管理、维修管理、投诉管理、用户管理 效果图&#xff…

ONLYOFFICE 文档开发者版 8.0:API和文档生成器更新

随着 8.0 版新功能的发布&#xff0c;我们更新了编辑器、文档生成器和插件的 API。请阅读本文了解详情。 PDF 支持 我们在 documentType 参数中添加了 pdf 文档这一类型。现在完全支持PDF文件*&#xff0c;包括含有可填写字段的文件&#xff0c;并且可以在ONLYOFFICE PDF 编辑…

Leetcode—134. 加油站【中等】

2024每日刷题&#xff08;113&#xff09; Leetcode—134. 加油站 实现代码 class Solution { public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int gasSum accumulate(gas.begin(), gas.end(), 0);int costSum accumulate(cost…

【SpringBoot】application配置(5)

type-aliases-package: com.rabbiter.cm.domaintype-aliases-package: 这个配置用于指定mybatis的别名&#xff0c;别名是一个简化的方式&#xff0c;让你在Mapper xml 文件中引用java类型&#xff0c;而不需要使用使用完整的类名。例如&#xff0c;如果你在 com.rabbiter.cm.d…

C#调用WechatOCR.exe实现本地OCR文字识别

最近遇到一个需求&#xff1a;有大量的扫描件需要还原为可编辑的文本&#xff0c;很显然需要用到图片OCR识别为文字技术。本来以为这个技术很普遍的&#xff0c;结果用了几个开源库&#xff0c;效果不理想。后来&#xff0c;用了取巧的方法&#xff0c;直接使用了WX的OCR识别模…

关于域名递归解析服务的问题

域名递归解析服务是互联网基础设施的重要组成部分&#xff0c;它允许用户通过域名来访问网站或应用程序。然而&#xff0c;在某些情况下&#xff0c;域名递归解析服务可能会出现问题&#xff0c;导致用户无法正常访问网站或应用程序。本文将探讨域名递归解析服务可能面临的问题…

必收藏!第六版CCF推荐会议C类国际学术会议!(中国计算机学会)

中国计算机学会 中国计算机学会&#xff08;CCF&#xff09;是全国性、学术性、非营利的学术团体&#xff0c;由从事计算机及相关科学技术领域的个人和单位自愿组成。作为独立社团法人&#xff0c;CCF是中国科学技术协会的成员之一&#xff0c;是全国一级学会&#xff01; CCF的…

nacos越权漏洞复现

1.低版本(nacos<1.4.1)默认白名单UA 开启鉴权功能后&#xff0c;服务端之间的请求也会通过鉴权系统的影响。考虑到服务端之间的通信应该是可信的&#xff0c;因此在1.2~1.4.0版本期间&#xff0c;通过User-Agent中是否包含Nacos-Server来进行判断请求是否来自其他服务端。 但…

python-产品篇-游戏-玛丽冒险

文章目录 开发环境要求运行方法代码效果 开发环境要求 本系统的软件开发及运行环境具体如下。 &#xff08;1&#xff09;操作系统&#xff1a;Windows 7、Windows 8、Windows 10。 &#xff08;2&#xff09;Python版本&#xff1a;Python 3.7.0。 &#xff08;3&#xff09;…

51单片机 跑马灯

#include <reg52.h>//毫秒级延时函数 void delay(int z) {int x,y;for(x z; x > 0; x--)for(y 114; y > 0 ; y--); }sbit LED1 P1^0x0; sbit LED2 P1^0x1; sbit LED3 P1^0x2; sbit LED4 P1^0x3; sbit LED5 P1^0x4; sbit LED6 P1^0x5; sbit LED7 P1^0x6; s…

【Linux】环境基础开发工具的使用之gdb详解(三)

前言&#xff1a;上一篇文章中我们讲解了Linux下的gcc与g的使用&#xff0c;今天我们将进一步的学习gdb与makefile来帮我们更好的理解与使用基础开发工具。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:Linux的深度刨析 &#x1f448; …

再识C语言 DAY15 【指针(中)理论结合实践】

文章目录 前言一、补充二、数组与指针指针运算 注意事项指针的应用传递参数&#xff08;指针的间接访问&#xff09;指针输出参数 如果您发现文章有错误请与我留言&#xff0c;感谢 前言 本文章总结于此视频 一、补充 指针即指针变量&#xff0c;用于存放其他数据单元&#xf…

代码随想录算法训练营DAY15 | 二叉树 (2)

一、LeetCode 102 二叉树的层序遍历 题目链接&#xff1a; 102.二叉树的层序遍历https://leetcode.cn/problems/binary-tree-level-order-traversal/ 思路&#xff1a;利用队列的先进先出特性&#xff0c;在处理本层节点的同时将下层节点入队&#xff0c;每次处理一层的节点&…

PKI - 04 证书授权颁发机构(CA) 数字证书

文章目录 PrePKI 、 CA 和 证书PKICA数字证书签发数字证书返回给实体安全的交换公钥 IKE数字签名认证 Pre PKI - 02 对称与非对称密钥算法 PKI - 03 密钥管理&#xff08;如何进行安全的公钥交换&#xff09; PKI 、 CA 和 证书 用通俗易懂的语言来解释一下PKI&#xff08;公…

【c++】STL详解(一):string类的使用

C标准模板库&#xff08;STL&#xff09;是C编程语言的重要组成部分&#xff0c;他提供了一系列模板化的通用类和函数&#xff0c;用于实现常见的数据结构和算法。 在STL中&#xff0c;string类作为处理字符串的基础设施&#xff0c;提供了丰富的功能来支持字符串的操作。本文将…