代码随想录-Day22

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

方法一:两次遍历

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {List<TreeNode> path_p = getPath(root, p);List<TreeNode> path_q = getPath(root, q);TreeNode ancestor = null;for (int i = 0; i < path_p.size() && i < path_q.size(); ++i) {if (path_p.get(i) == path_q.get(i)) {ancestor = path_p.get(i);} else {break;}}return ancestor;}public List<TreeNode> getPath(TreeNode root, TreeNode target) {List<TreeNode> path = new ArrayList<TreeNode>();TreeNode node = root;while (node != target) {path.add(node);if (target.val < node.val) {node = node.left;} else {node = node.right;}}path.add(node);return path;}
}

这段代码定义了一个名为 Solution 的类,用于求解二叉搜索树(Binary Search Tree, BST)中两个指定节点的最近公共祖先(Lowest Common Ancestor, LCA)。类中包含两个方法:

  1. lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)

    • 功能:该方法接收BST的根节点 root 和需要寻找LCA的两个节点 pq 作为参数,返回这两个节点的最近公共祖先。
    • 实现:首先,分别调用 getPath 方法获取节点 pq 到根节点的路径(以节点列表形式存储)。然后,遍历这两个路径,找到路径中最后一个相同的节点,即为最近公共祖先。如果两个路径没有共同节点(理论上在BST中不会发生,除非 pq 不在树中),则返回 null(虽然代码中未直接处理这种情况,但循环结束时 ancestor 仍为 null)。
  2. getPath(TreeNode root, TreeNode target)

    • 功能:该方法接收BST的根节点 root 和目标节点 target,返回从根到目标节点的路径上的所有节点列表。
    • 实现:通过一个循环不断比较当前节点与目标节点的值,决定是向左子树还是右子树移动。同时,将访问过的节点按路径顺序添加到列表 path 中。当找到目标节点时,将目标节点也添加到路径列表,并返回整个路径。

注意,这段代码的高效运行依赖于输入是二叉搜索树的特性,即树中任意节点的左子树所有节点的值都小于该节点的值,右子树所有节点的值都大于该节点的值。这使得在寻找特定值的节点时,可以快速地在树中进行定向移动,而不需要回溯,因此每个 getPath 方法的时间复杂度为O(log n),其中n是树中的节点数。整体的 lowestCommonAncestor 方法的时间复杂度也是O(log n),因为两个路径的最长公共前缀长度不会超过树的高度。

方法二:一次遍历

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {TreeNode ancestor = root;while (true) {if (p.val < ancestor.val && q.val < ancestor.val) {ancestor = ancestor.left;} else if (p.val > ancestor.val && q.val > ancestor.val) {ancestor = ancestor.right;} else {break;}}return ancestor;}
}

这段代码定义了一个名为 Solution 的类,其中包含一个方法 lowestCommonAncestor,用于在给定的二叉搜索树(BST)中找到两个指定节点 pq 的最近公共祖先(LCA)。这个方法直接利用了BST的性质(即左子树所有节点的值小于根节点值,右子树所有节点的值大于根节点值),以迭代而非递归的方式高效地解决了问题。以下是代码的详细解释:

  • 方法签名public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) 接受三个参数,分别是BST的根节点 root,以及需要找LCA的两个节点 pq

  • 初始化祖先节点:首先将 ancestor 初始化为根节点 root

  • 循环查找:进入一个 while 循环,循环条件默认为 true,意味着它将一直执行,直到通过 break 语句跳出循环。

    • 在循环内,首先检查 pq 的值与当前 ancestor 节点值的关系:
      • 如果 pq 的值都小于 ancestor 的值,说明它们都在当前节点的左子树中,因此将 ancestor 更新为其左子节点。
      • 如果 pq 的值都大于 ancestor 的值,说明它们都在当前节点的右子树中,因此将 ancestor 更新为其右子节点。
      • 如果以上两种情况都不满足,说明当前 ancestor 节点满足以下至少一种情况:
        • 它正好是 pq 中的一个。
        • 它位于 pq 之间,即一个在它的左子树,另一个在它的右子树,或者两者都在同一边但当前节点就是最近的共同祖先。
      • 在这种情况下,通过 break 退出循环,因为已经找到了最近公共祖先。
  • 返回结果:循环结束后,ancestor 节点即为所求的最近公共祖先,直接返回该节点。

这种方法的时间复杂度为 O(h),其中 h 是树的高度,因为在最坏情况下,我们可能需要从根节点一直走到 pq 中较深的那个节点。由于是二叉搜索树,高度 h 最坏情况下为 n(树退化为链表的情况),最好情况下为 log(n)。空间复杂度为 O(1),因为我们只使用了固定数量的指针变量,没有使用额外的空间来存储节点路径等。

701. 二叉搜索树中的插入操作

class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {if (root == null) {return new TreeNode(val);}TreeNode pos = root;while (pos != null) {if (val < pos.val) {if (pos.left == null) {pos.left = new TreeNode(val);break;} else {pos = pos.left;}} else {if (pos.right == null) {pos.right = new TreeNode(val);break;} else {pos = pos.right;}}}return root;}
}

这段代码定义了一个名为 Solution 的类,其中包含一个方法 insertIntoBST,该方法用于将一个值插入到给定的二叉搜索树(Binary Search Tree, BST)中。二叉搜索树的特性是:对于任意一个节点,其左子树中的所有节点的值都小于该节点的值,其右子树中的所有节点的值都大于该节点的值。以下是方法的逻辑解析:

  • 方法签名public TreeNode insertIntoBST(TreeNode root, int val) 接受两个参数,一个是BST的根节点 root,另一个是要插入的值 val

  • 基本情况处理:首先检查 root 是否为空。如果为空,说明当前树为空,那么直接创建一个新的 TreeNode,其值为 val,并返回这个新节点作为新树的根。

  • 寻找插入位置:如果根节点不为空,声明一个指针 pos 指向当前考虑的节点(初始化为根节点 root),然后进入一个 while 循环,用于找到插入新节点的位置。

    • 在循环中,如果 val 小于 pos 节点的值,则向左子树移动;如果 val 大于或等于 pos 节点的值,则向右子树移动。每次移动时,如果遇到空的子节点(即找到了插入位置),则在相应位置创建一个新节点,值为 val,并跳出循环。
  • 返回结果:循环结束后,无论是否插入新节点,根节点 root 的引用都保持不变,直接返回 root 即可。因为插入操作是在原有的树结构基础上进行的,没有改变根节点本身,只是在其某个子树上新增了节点。

这种方法保持了二叉搜索树的性质,插入操作的时间复杂度在最坏情况下为 O(H),其中 H 是树的高度。对于平衡的二叉搜索树,平均情况下插入操作的时间复杂度为 O(log N),N 为树中节点的数量。

450. 删除二叉搜索树中的节点

方法一:递归

class Solution {public TreeNode deleteNode(TreeNode root, int key) {if (root == null) {return null;}if (root.val > key) {root.left = deleteNode(root.left, key);return root;}if (root.val < key) {root.right = deleteNode(root.right, key);return root;}if (root.val == key) {if (root.left == null && root.right == null) {return null;}if (root.right == null) {return root.left;}if (root.left == null) {return root.right;}TreeNode successor = root.right;while (successor.left != null) {successor = successor.left;}root.right = deleteNode(root.right, successor.val);successor.right = root.right;successor.left = root.left;return successor;}return root;}
}

这段代码定义了一个名为 Solution 的类,其中包含一个方法 deleteNode,用于在给定的二叉搜索树(BST)中删除具有给定值的节点。二叉搜索树的特性是左子树中的所有节点的值小于当前节点值,右子树中的所有节点的值大于当前节点值。下面是代码逻辑的详细解析:

  1. 基本情况处理:首先检查根节点是否为空,如果为空,则直接返回 null,表示树为空或目标节点不存在。

  2. 查找目标节点:利用BST的性质进行查找。如果目标值 key 小于当前节点值 root.val,则在左子树中递归删除;如果 key 大于当前节点值,则在右子树中递归删除。这一步骤会一直进行到找到目标节点或递归到空节点为止。

  3. 删除目标节点

    • 当找到目标节点(即 root.val == key)时,有三种情况:
      • 叶子节点:如果目标节点没有左右子节点,直接返回 null,让其父节点指向 null 达到删除效果。
      • 仅有一个子节点:如果目标节点只有左子节点或右子节点,直接返回其非空的子节点,使父节点指向这个子节点。
      • 有两个子节点:找到目标节点的后继节点(即右子树中的最小节点 successor),用后继节点替换当前目标节点。然后在右子树中递归删除这个后继节点(因为后继节点可能是其所在子树的最小值,也可能有右子节点,故需要递归删除以保持BST性质)。后继节点的左子树挂载到原目标节点的左子树上,原目标节点的右子树挂载到后继节点的右子树上,这样既删除了目标节点,又保持了BST的结构。
  4. 返回处理结果:在递归的每一步中,直接返回处理后的子树根节点,这样可以保证上一层递归能够正确接收到更新后的子树状态。

通过上述逻辑,该方法能够有效地在二叉搜索树中删除指定值的节点,同时保持树的二叉搜索特性。

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

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

相关文章

k8s部署calico遇到的问题

kubernetes安装calico calico官网 环境&#xff1a;centos7.9&#xff0c;calico 3.23&#xff0c;kuberadm 1.26 问题1&#xff1a;执行kubectl create -f calico.yml后报错如下 error: resource mapping not found for name: “tigera-operator” namespace: “” from “…

echarts-dataset,graphic,dataZoom, toolbox

dataset数据集配置数据 dataset数据集&#xff0c;也可以完成数据的映射&#xff0c;一般用于一段数据画多个图表 例子&#xff1a; options {tooltip: {},dataset: {source: [["product", "2015", "2016", "2017"],["test&q…

HTTP Basic Access Authentication Schema

HTTP Basic Access Authentication Schema 背景介绍流程安全缺陷参考 背景 本文内容大多基于网上其他参考文章及资料整理后所得&#xff0c;并非原创&#xff0c;目的是为了需要时方便查看。 介绍 HTTP Basic Access Authentication Schema&#xff0c;HTTP 基本访问认证模式…

【在 Windows 上使用 ADB 安装 Android 设备上的 atx-agent】

在进行 Android 应用的 UI 自动化测试时&#xff0c;通常需要在设备上安装一些辅助工具。其中一个常用的工具是 atx-agent&#xff0c;它可以帮助我们在 Android 设备上进行 UI 自动化操作。本文将介绍如何在 Windows 环境下使用 ADB 安装 Android 设备上的 atx-agent。 1. 下…

ThreadLocal:熟悉的陌生词,你应该要知道的。

Hi,大家好&#xff0c;我是抢老婆酸奶的小肥仔。 在很多的地方&#xff0c;我们都能看到ThreadLocal的身影&#xff0c;也会用到它&#xff0c;但是我们真的就了解它吗&#xff1f; 今天我们来叨叨这个我们既熟悉又陌生的小伙伴&#xff0c;废话不多说开整。 1、啥是ThreadL…

云原生架构内涵_3.主要架构模式

云原生架构有非常多的架构模式&#xff0c;这里列举一些对应用收益更大的主要架构模式&#xff0c;如服务化架构模式、Mesh化架构模式、Serverless模式、存储计算分离模式、分布式事务模式、可观测架构、事件驱动架构等。 1.服务化架构模式 服务化架构是云时代构建云原生应用的…

[ C++ ] 深入理解模板( 初 阶 )

函数模板 函数模板格式 template <typename T1, typename T2,......,typename Tn> 返回值类型 函数名(参数列表){} 注意&#xff1a; typename是用来定义模板参数关键字&#xff0c;也可以使用class(切记&#xff1a;不能使用struct代替class) 函数模板的实例化 模板参数…

鸿蒙开发接口图形图像:【WebGL】

WebGL WebGL提供图形绘制的能力&#xff0c;包括对当前绘制图形的位置、颜色等进行处理。 WebGL标准图形API&#xff0c;对应OpenGL ES 2.0特性集。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md…

c++编程(15)——list的模拟实现

欢迎来到博主的专栏——c编程 博主ID&#xff1a;代码小豪 文章目录 前言list的数据结构list的默认构造尾插与尾删iterator插入和删除构造、析构、赋值copy构造initializer_list构造operator 析构函数 前言 受限于博主当前的技术水平&#xff0c;暂时还不能模拟实现出STL当中用…

C语言从头学13——流程控制(二)

接着学习流程控制&#xff0c;并继续上一篇的编号。 4、while 语句 while语句用于循环结构&#xff0c;满足条件时&#xff0c;不断执行循环体&#xff0c;直到条件不满足时退出。如果 一直满足循环条件无法结束循环&#xff0c;会陷入死循环&#xff0c;这是应当避免的…

E. Binary Deque[双指针好思维题]

Binary Deque 题面翻译 有多组数据。 每组数据给出 n n n 个数&#xff0c;每个数为 0 0 0 或 1 1 1 。你可以选择从两边删数&#xff0c;求至少删几个数才可以使剩下的数总和为 s s s 。 如果不能达到 s s s &#xff0c;则输出 − 1 -1 −1 。 题目描述 Slavic h…

ABAP 在增强中COMMIT

前言 呃&#xff0c;又是很磨人的需求&#xff0c;正常情况下是不允许在增强中COMMIT的&#xff0c;会影响源程序本身的逻辑&#xff0c;但是这个需求就得这么干… 就是在交货单增强里面要再调用一次交货单BAPI&#xff0c;通过SO的交货单自动创建STO的交货单&#xff0c;如果…

pod install 报错 ‘SDK does not contain ‘libarclite‘ at the path...‘

报错内容&#xff1a; SDK does not contain ‘libarclite’ at the path ‘/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a’; 这是报错已经很明确告诉我们&#xff0c;Xcode默认的工具链中缺少一个工具…

使用AXI MIG/Proc Sys Reset

使用AXI MIG/Proc Sys Reset 重要&#xff01;仅当您的设计中包含AXI MIG时&#xff0c;才执行以下步骤。 AXI-MIG的连接接口 1.选择在/mig_7series_0/S_AXI上运行连接自动化。 2.选择/micblaze_0&#xff08;缓存&#xff09;或/micblaze _0&#xff08;Periph&#xff09;选项…

【Spring】AOP——通知(Advice)

1、通知&#xff08;Advice&#xff09; 1.1简介 在AOP中&#xff0c;通知&#xff08;Advice&#xff09;是切面&#xff08;Aspect&#xff09;中的一部分&#xff0c;用于定义在连接点&#xff08;Joinpoint&#xff09;处应该执行的操作。通知类型可以在AOP框架中配置和使…

在Android中解析XML文件并在RecyclerView中显示

1. 引言 最近工作有解析外部xml文件在App中显示的需求&#xff0c;特来写篇文章记录一下&#xff0c;方便下次使用。 2. 准备工作 首先&#xff0c;在项目的AndroidManifest.xml文件中添加读取外部存储的权限声明。 <uses-permission android:name"android.permiss…

Java程序设计

一 Java基础知识 1 Java语言概述 1.1 发展历史 1.2 Java应用领域 Web开发&#xff1a;电子商务网站、内部管理系统、社交网络、门户网站移动开发&#xff1a;Android开发桌面开发&#xff1a;办公软件、游戏、工具软件企业应用开发&#xff1a;客户关系管理、企业资源计划、…

3DEXPERIENCE DELMIA Role: RVN - Robotics Virtual Commissioning Analyst

Discipline: Robotics Role: RVN - Robotics Virtual Commissioning Analyst 通过准确地模拟连接到PLC程序的机器人、设备和传感器&#xff0c;在制造虚拟孪生上执行虚拟调试情景 为任何机器人角色的多周期情景创建传感器&#xff0c;生成和变换零件启用 PLC 程序的虚拟验证和…

visio中画乘法器加法器符号

情景&#xff1a;在进行rtl设计时&#xff0c;需要画出简单的电路实现图&#xff0c;需要用到加法器&#xff0c;乘法器的符号。 位置&#xff1a;在visio的更多形状中&#xff0c;找到如下图的位置&#xff0c;进行添加&#xff0c;即可 最终效果&#xff1a; 可以满足我们日…

python监控windows服务器的进程和服务

需求&#xff1a;软件公司提供的软件服务在服务器上会莫名其妙的挂掉&#xff0c;他们采用的方法也只有重启服务器&#xff0c;重启时间太久了&#xff0c;所以想弄一个监测进程和服务的程序&#xff0c;监测到挂了就重启进程或者服务 import psutil import time import sub…