算法日记day 22

news2024/9/17 4:40:20

一、二叉搜索树中的插入操作

题目:

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

示例 1:

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]

示例 3:

输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]

 思路:

只需要按照二叉搜索树的规则,遇到空节点时创建新的节点并插入即可,不需要去刻意的改变树的结构

代码:

public TreeNode insertIntoBST(TreeNode root, int val) {
    // 如果根节点为空,直接创建一个新节点作为根节点并返回
    if (root == null) {
        return new TreeNode(val);
    }
    
    // 如果插入值小于当前节点的值,递归地将值插入到左子树
    if (val < root.val) {
        root.left = insertIntoBST(root.left, val);
    }
    
    // 如果插入值大于当前节点的值,递归地将值插入到右子树
    if (val > root.val) {
        root.right = insertIntoBST(root.right, val);
    }
    
    // 返回根节点
    return root;
}
  • 如果当前根节点 root 为空,说明当前位置可以插入新节点 val,因此创建一个新的 TreeNode 对象并返回,这个节点成为新的根节点。
  • 如果插入值 val 小于当前节点 root 的值,则将 val 插入到当前节点的左子树中。递归调用 insertIntoBST 方法,将返回的左子树根节点赋值给 root.left
  • 如果插入值 val 大于当前节点 root 的值,则将 val 插入到当前节点的右子树中。递归调用 insertIntoBST 方法,将返回的右子树根节点赋值给 root.right

 

二、删除二叉树中的节点

题目:

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。


示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

思路:

不但要删除指定节点,还要保持原二叉搜索树的性质不变,总共分为五种情况:

1、节点在树中没有找到,直接返回null

2、节点的左右子树均为空(即要删除的节点为叶子节点)

3、节点的左子树为空,右子树不为空

4、节点的右子树为空,左子树不为空

5、节点的左右子树均不为空,这种情况最为复杂,当要删除的左右子树均存在时,可以将其左或者右节点作为其新的父节点添加到上面。当以右子树节点为新的父节点时,由于二叉搜索树的特性,右子树的值一定比左子树的值大,因此遍历寻找右子树中最左端的节点,然后将将要删去的节点的左子树全部放在该节点下,反之,如果以左子树节点为新的父节点,遍历该左子树最右端的子节点,然后将将要删去的节点的右子树节点全部放在该节点下,全部修改完毕后,删除指定节点,将其子节点返回给上一层,最后输出修改后的二叉搜索树。

代码:

public TreeNode deleteNode(TreeNode root, int key) {
    // 如果根节点为空,直接返回null
    if (root == null)
        return null;
    
    // 如果找到要删除的节点
    if (root.val == key) {
        // Case 1: 要删除的节点是叶子节点(没有子节点)
        if (root.left == null && root.right == null) {
            return null; // 直接返回null,相当于删除这个节点
        }
        // Case 2: 要删除的节点只有右子节点
        else if (root.left == null && root.right != null) {
            return root.right; // 返回右子节点,用以替换被删除的节点
        }
        // Case 3: 要删除的节点只有左子节点
        else if (root.left != null && root.right == null) {
            return root.left; // 返回左子节点,用以替换被删除的节点
        }
        // Case 4: 要删除的节点有左右子节点
        else {
            // 找到右子树中最小的节点(后继节点)
            TreeNode cur = root.right;
            //一直向右子树中的最左端遍历,当左节点为null时,此时cur指向的就是值最小的节点
            while (cur.left != null) {
                cur = cur.left;
            }
            // 将要删除的节点的左子树挂在后继节点的左子树上
            cur.left = root.left;
            // 删除指定的节点,并返回后继节点作为新的子树根节点
            root = root.right;
            return root;
        }
    }
    
    // 如果要删除的节点值小于当前节点值,递归地在左子树中删除
    if (key < root.val)
        root.left = deleteNode(root.left, key);
    
    // 如果要删除的节点值大于当前节点值,递归地在右子树中删除
    if (key > root.val)
        root.right = deleteNode(root.right, key);
    
    // 返回更新后的根节点
    return root;
}
  • 如果根节点 root 为空,直接返回 null,因为无法在空树中删除节点。
  • 当前节点的值等于要删除的值 key 时,进入删除节点的逻辑。
  • Case 1: 要删除的节点是叶子节点(没有子节点),直接返回 null
  • Case 2: 要删除的节点只有右子节点,返回右子节点,用它来替换被删除的节点。
  • Case 3: 要删除的节点只有左子节点,返回左子节点,用它来替换被删除的节点。
  • Case 4: 要删除的节点有左右子节点,找到右子树中最小的节点作为后继节点,将要删除节点的左子树挂在后继节点的左子树上,然后返回右子树作为新的子树根节点。
  • 如果要删除的值 key 小于当前节点的值,递归地在左子树中删除。
  • 如果要删除的值 key 大于当前节点的值,递归地在右子树中删除。
  • 每次递归调用返回更新后的当前节点 root,确保整棵树的结构被正确更新。

三、修建二叉搜索树 

题目:

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例 1:

输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]

示例 2:

输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]

思路:

在我们递归操作时,当其左节点小于区间是,其左节点的左节点也不在区间内,但其左节点的右节点有可能存在于区间中,因此需要对右区间额外的进行递归,同理,当右节点大于区间,但是其右节点的左节点有可能在区间中,也需要进行额外的操作

代码:

public TreeNode trimBST(TreeNode root, int low, int high) {
    // 如果根节点为空,直接返回null
    if (root == null) {
        return null;
    }
    
    // 如果当前节点的值小于low,说明当前节点及其左子树都不在范围内,应该修剪右子树
    if (root.val < low) {
        return trimBST(root.right, low, high);
    }
    
    // 如果当前节点的值大于high,说明当前节点及其右子树都不在范围内,应该修剪左子树
    if (root.val > high) {
        return trimBST(root.left, low, high);
    }
    
    // 如果当前节点的值在 [low, high] 范围内,则递归修剪左右子树
    root.left = trimBST(root.left, low, high);
    root.right = trimBST(root.right, low, high);
    
    // 返回修剪后的根节点
    return root;
}
  • 如果当前节点的值小于 low

    • 这意味着当前节点及其左子树的所有节点都不可能在范围 [low, high] 内,因此应该将当前节点及其左子树都丢弃,递归地修剪右子树 root.right
  • 如果当前节点的值大于 high

    • 类似地,当前节点及其右子树的所有节点都不在范围 [low, high] 内,应该将当前节点及其右子树都丢弃,递归地修剪左子树 root.left
  • 如果当前节点的值在 [low, high] 范围内

    • 此时,当前节点满足条件,但它的左右子树可能包含不符合范围的节点,因此需要递归地修剪左子树和右子树。

今天的学习就到这里

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

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

相关文章

Python学习笔记46:游戏篇之外星人入侵(七)

前言 到目前为止&#xff0c;我们已经完成了游戏窗口的创建&#xff0c;飞船的加载&#xff0c;飞船的移动&#xff0c;发射子弹等功能。很高兴的说一声&#xff0c;基础的游戏功能已经完成一半了&#xff0c;再过几天我们就可以尝试驾驶 飞船击毁外星人了。当然&#xff0c;计…

【优秀python web系统毕设】基于python的全国招聘数据分析可视化系统,包括随机森林算法

1.1 研究背景 自1997年互联网开始在国内的招聘行业发展至今已有二十几年的历史&#xff0c;互联网招聘进入了蓬勃发展的“黄金时代”。根据智研咨询发布的《2023年中国互联网招聘行业发展现状》报告显示&#xff0c;截至2023年5月&#xff0c;中国互联网招聘平台中&#xff0c…

数据结构(Java):反射枚举Lambda表达式

目录 1、反射 1.1 反射的定义 1.2 反射机制的原理 1.3 反射相关类 1.4 Class类 1.4.1 相关方法 1.4.1.1 常用获得类相关的方法 ​编辑 1.4.1.2 常用获得类中属性相关的方法 1.4.1.3 获得类中构造器相关的方法 1.4.1.4 获得类中方法相关的方法 1.4.2 获取Class对象 1.…

DeFi革命:揭秘去中心化金融的核心技术与实操指南

目录 DeFi&#xff08;去中心化金融&#xff09;综述 基本特点 第一&#xff0c;DeFi 是无许可的金融 第二&#xff0c;DeFi 是无门槛的金融 第三&#xff0c;DeFi 是无人驾驶的金融 典型商业模式 闪电贷 MakerDAO 面临的挑战 DeFi技术要点 椭圆曲线签名 EIP-712:…

IS-LM模型的公式与应用解析

IS-LM模型的公式与应用解析 IS-LM模型的核心作用 IS-LM模型是宏观经济学中的一个重要工具&#xff0c;用于分析财政政策和货币政策对经济的影响。IS曲线代表商品市场均衡&#xff0c;LM曲线代表货币市场均衡。两条曲线的交点表示商品市场和货币市场同时达到均衡时的利率和收入…

MySQL笔记3——高级数据查询语句DQL

多表联查 多表联查可以通过连接运算实现&#xff0c;即将多张表通过主外键关系关联在一起进行查询。下图提供了多表联查 时用到的数据库表之间的关系。 等值查询和非等值查询 非等值查询&#xff1a;SELECT * FROM 表1&#xff0c;表2 等值查询&#xff1a;SELECT * FROM 表…

DDR3布线时候的经验总结

摆放BGA下面的滤波电容的时候注意不要让两个电容的电源和地对着头放&#xff0c;手工焊接时候容易短路 阻抗层必须是实心铜皮覆盖&#xff1a; &#xff08;3&#xff09;阻抗线一定要有阻抗参考层&#xff0c;一般以相邻的接地或电源层做参考层&#xff08;如顶层阻抗线&…

人工智能技术的分析与探讨

《人工智能技术的分析与探讨》 摘要&#xff1a; 本文深入探讨了人工智能技术在多个领域的应用&#xff0c;包括智能感知、智能语音、智能问答、智能机器人、智能制造、智能医疗等。详细阐述了这些技术在当前的应用现状和主要场景&#xff0c;展示了一些典型的应用案例&#…

放大电路总结

补充: 只有直流移动时才有Rbe动态等效电阻 从RsUs看进去,实际上不管接了什么东西都能够看成是一个Ri(输入电阻) Ri Ui/Ii Rb//Rbe Ui/Us Ri/(RiRs) Aus (Uo/Ui)*(Ui/Us) Au *Ri/(RiRs) 当前面是一个电压源的信号 我们就需要输入电阻更大 Ro--->输出电阻--->将…

学习C语言第十四天(指针练习)

1.第一题C 2.第二题C 3.第三题 00345 short类型解引用一次访问两个字节 4.第四题 6&#xff0c;12 5.第五题C 6.第六题 下面代码结果是0x11223300 7.第七题 int main() {int a 0;int n 0;scanf("%d %d",&a,&n);int i 0;int k 0;int sum 0;for (i 0;…

创维汽车滁州永通体验中心开业仪式暨超充车型区域上市会圆满成功

2024年7月20日&#xff0c;创维汽车滁州永通体验中心盛大开业&#xff0c;当日&#xff0c;创维汽车市场部经理周世鹏、安徽大区总监王大明等领导参加本次开业盛典&#xff0c;共同见证创维汽车滁州永通体验中心成功落地。 2021年&#xff0c;新能源乘用车高速发展&#xff0c;…

安装CUDA Cudnn Pytorch(GPU版本)步骤

一.先看自己的电脑NVIDIA 支持CUDA版本是多少&#xff1f; 1.打开NVIDIA控制面板 2.点击帮助---系统信息--组件 我的支持CUDA11.6 二.再看支持Pytorch的CUDA版本 三.打开CUDA官网 下载CUDA 11.6 下载好后&#xff0c;安装 选择 自定义 然后安装位置 &#xff08;先去F盘…

MySQL可重复读的隔离机制下是否彻底解决了幻读?

答案&#xff1a;没有彻底解决。 一、什么是幻读&#xff1f; 当同一个查询在不同时间产生不同的结果集时&#xff0c;事务中就会出现幻读问题。 幻读关注的是记录数量的不同。 不可重复读关注的是记录内容的不同。 二、快照读和当前读 InnoDB引擎的默认隔离级别是可重复读&…

vue3 命令运行窗口暴露网络地址,以及修改端口号

一般情况下这里的地址是隐藏的 这里加上 --host 可以暴露网络地址&#xff0c;再加上--port --8080 就可以将端口号修改为8080&#xff08;修改后边的数字就可以修改为你想要的端口号&#xff09;

pytorch-训练自定义数据集实战

目录 1. 步骤2. 加载数据2.1 继承Dataset2.1.1 生成name2label2.1.2 生成image path, label的文件2.1.3 __len__2.1.3 __getitem__2.1.4 数据切分为train、val、test 3. 建立模型4. 训练和测试4. 完整代码 1. 步骤 加载数据创建模型训练和测试迁移学习 2. 加载数据 这里以宝…

打造创新项目:从理念到市场的成功之路

打造创新项目&#xff1a;从理念到市场的成功之路 前言为何创新&#xff1f;如何创新&#xff1f;创新的意义 一、深入市场&#xff0c;洞察行业脉搏二、精准定位&#xff0c;锁定目标市场三、全面评估&#xff0c;确保项目可行性四、创新引领&#xff0c;打造独特卖点五、开放…

二叉树_堆(下卷)

前言 接前面两篇的内容&#xff0c;接着往下讲二叉树_堆相关的内容。 正文 那么&#xff0c;回到冒泡排序与堆排序的比较。 我们知道冒泡排序的时间复杂度为 O ( N 2 ) O(N^2) O(N2)&#xff0c;这个效率是不太好的。 那么&#xff0c;我们的堆排序的时间复杂度如何呢&…

Linux:进程概述(什么是进程、进程控制块PCB、并发与并行、进程的状态、进程的相关命令)

进程概述 (1)What&#xff08;什么是进程&#xff09; 程序&#xff1a;磁盘上的可执行文件&#xff0c;它占用磁盘、是一个静态概念 进程&#xff1a;程序执行之后的状态&#xff0c;占用CPU和内存&#xff0c;是一个动态概念&#xff1b;每一个进程都有一个对应的进程控制块…

云计算复习--分布式存储系统

分布式存储 分布式存储系统是一种将数据分散在多个独立节点上&#xff0c;并通过网络进行数据传输和访问的存储系统 分布式存储的特点&#xff1a;可扩展性、高可用性、容错性、高性能等。分布式存储系统能够水平扩展存储容量和性能&#xff0c;提供持续可用的数据存储服务&am…

【在开发小程序的时候如何排查问题】

在开发小程序的时候如何排查问题 在最近开发小程序的时候&#xff0c;经常出现本地在浏览器中调试没有问题&#xff0c;但是一发布到预发环境就出现各种个样的问题 手机兼用性问题 有时候会出现苹果&#x1f34e;手机键盘弹出&#xff0c;导致ui界面高度出现异常边界问题&#…