Day 22 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

news2025/6/21 0:42:42

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

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

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

示例 1:

  • 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
  • 输出: 6
  • 解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

  • 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
  • 输出: 2
  • 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

​ 充分利用二叉搜索树的有序特性,判断节点是否处于p q节点中间即可找到最近的公共祖先;

	TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q){
        if(cur == NULL)	reeturn nullptr;
        if (cur->val > p->val && cur->val > q->val) {   // 左
            TreeNode* left = traversal(cur->left, p, q);
            if (left != NULL) {
                return left;
            }
        }

       	if (cur->val < p->val && cur->val < q->val) {   // 右
            TreeNode* right = traversal(cur->right, p, q);
            if (right != NULL) {
                return right;
            }
        }
        return cur;
    }

​ 题解代码如下:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root->val > p->val && root->val > q->val) {
            return lowestCommonAncestor(root->left, p, q);
        } else if (root->val < p->val && root->val < q->val) {
            return lowestCommonAncestor(root->right, p, q);
        } else return root;
    }
};

二叉搜索树中的插入操作

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

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

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

提示:

  • 给定的树上的节点数介于 0 和 10^4 之间
  • 每个节点都有一个唯一整数值,取值范围从 0 到 10^8
  • -10^8 <= val <= 10^8
  • 新值和原始二叉搜索树中的任意节点值都不同

​ 由于题目给出的提示是可以不限制二叉树的结构的,那么可以不改变二叉树结构的情况下将所有元素全部插入到叶节点;

​ 递归实现如下:

    TreeNode* traversal(TreeNode* root, int val) {
        if (root == NULL) {//此时为叶子节点
            TreeNode* node = new TreeNode(val);
            return node;//返回包含新节点的父节点
        }
        if (root->val > val) root->left = traversal(root->left, val);//利用二叉搜索树性质寻找传入节点位置
        if (root->val < val) root->right = traversal(root->right, val);
        return root;//返回上层节点,最终返回根节点
    }

删除二叉搜索树中的节点

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

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

首先找到需要删除的节点; 如果找到了,删除它。 说明: 要求算法时间复杂度为 O ( h ) O(h) O(h),h 为树的高度。

示例:

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

​ 难度来了,改变二叉搜索树的结构;

​ 那么就有四种删除情况需要讨论:

​ 1.删除叶子节点(左右都为空的节点):最简单的操作方式;

​ 2.删除左不为空右为空的节点:让该节点的父节点指向左子节点;

​ 3.删除左为空右不为空的节点:让该节点的父节点指向右子节点;

​ 4.删除左右都不为空的节点:可以用左子树的最右下的节点(或右子树最左下的节点)替代当前节点来接收原本的右子树(或左子树),然后直接用父节点指向此节点的左子树(或右子树);此处代码实现需要new一个TreeNode型的临时节点来存储节点,注意内存释放;

​ 整体代码实现如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root)    return root;//没有可删除元素,直接返回空
        if(root->val == key){//进入删除节点逻辑
            if(!root->left && !root->right){//左右节点都为空,第一种
                delete root;
                return NULL;
            }
            else if(root->left && !root->right){//左子树非空,右子树为空
                TreeNode* tNode = root->left;//实现用root->left替换root;
                delete root;
                return tNode;
            }
            else if(root->right && !root->left){//左子树为空,右子树非空
                TreeNode* tNode = root->right;//实现用root->right替换root;
                delete root;
                return tNode;
            }
            else{//左右子树均非空
            //此处选择左子树替换的方式实现,定义cur为右子树节点
                TreeNode* cur = root->right;
                while(cur->left)    cur = cur->left;//得到右子树左下角的节点
                cur->left = root->left;// 把要删除的节点(root)左子树放在cur的左孩子的位置
                TreeNode* temp = root;
                root = root->right;// 返回旧root的右孩子作为新root
                delete temp;
                return root;
            }
        }
        if(root->val > key) root->left = deleteNode(root->left, key);
        if(root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};
    if(root->val > key) root->left = deleteNode(root->left, key);
        if(root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

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

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

相关文章

2024年CISP认证详细报考流程和条件,建议收藏!

CISP&#xff08;Certified Information Security Professional&#xff0c;注册信息安全专业人员&#xff09;证书是由中国信息安全测评中心&#xff08;CNITSEC&#xff09;颁发的专业资质证书&#xff0c;旨在为信息安全领域培养和认证具备一定专业水平的安全人才。CISP证书…

IDEA 导出jar无法执行 错误: 找不到或无法加载主类

1、首先配置正确Project Struct 保证需要引用的jar包库添加到Libraries里&#xff0c;尽管添加到Modules里依然可以测试运行或调试&#xff0c;但导出的jar包会遇到问题。 2、导出jar&#xff0c;方式选择如下 选择”From modules with dependencies" 然后去掉以上“Extr…

【C语言基础】:编译和链接(计算机中的翻译官)

文章目录 一、翻译环境和运行环境1. 翻译环境1.1 编译1.1.1 预处理1.1.2 编译1.1.3 汇编 1.2 链接 2. 运行环境 一、翻译环境和运行环境 我们在Visual Studio上写的C语言代码其实都是一些文本信息&#xff0c;计算机是不能够直接执行他们的&#xff0c;计算机只能够执行二进制…

机器人方向控制中应用的磁阻角度传感芯片

磁阻传感器提供的输出信号几乎不受磁场变动、磁温度系数、磁传感器距离与位置变动影响&#xff0c;可以达到高准确度与高效能&#xff0c;因此相当适合各种要求严格的车用电子与工业控制的应用。所以它远比采用其它传感方法的器件更具有优势。 机器人的应用日渐广泛&#xff0…

linux-docker删除redis容器

1、查看已经安装的redis镜像 docker ps2、通过别名或者通过容器ID&#xff1a;docker stop name/id docker stop 019814493c7a # id停止3、删除容器&#xff1a;可以通过name或id docker rm 019814493c7a # 通过id删除容器4、删除镜像&#xff1a; docker images # …

缓存策略以及如何选择正确的策略

正确地使用缓存可以减少系统响应的时间&#xff0c;降低数据库负载&#xff0c;反之可能带来相反的效果。因此&#xff0c;就必须了解有哪些缓存策略&#xff0c;以及如何根据实际使用场景选择合适的缓存策略。 缓存策略取决于数据和数据访问模式&#xff0c;即&#xff0c;数…

DSP笔记10-CPU定时器

28335有三个CPU定时器 高位寄存器H CPU定时器工作原理 周期寄存器PRDH:PRD 计数器寄存器TIMH:TIM 周期寄存器PRDH:PRD赋值后装在到计数器寄存器TIMH:TIM&#xff0c;TIMCLK&#xff08;脉冲&#xff09;减1&#xff0c;直至为0。 TIMCLK&#xff08;脉冲&#xff09;通过定…

yolov8多分支任务头训练

目前已知的yolov8可以针对多个任务进行单独训练,但是暂时还没有开放针对多个任务头同时进行训练的教程,本文章针对yolov8的多任务训练进行详细介绍。 先放上效果图: 三个任务,分别是目标检测、可行驶区域、车道线,具体步骤请往下看。 一、环境配置 从如下github下载代码…

idm线程越多越好吗 idm线程数多少合适 IDM百度云下载 IDM下载器如何修改线程数

IDM&#xff08;Internet Download Manager&#xff09;是一款流行的网络下载器&#xff0c;它支持多线程下载&#xff0c;这意味着它可以同时建立多个连接来下载文件的不同部分&#xff0c;从而提高下载速度。我们在使用IDM的时候总是有很多疑问&#xff0c;今天我们学习IDM线…

【科学计量】剔除来自unknown的机构与作者文献文献——数据清洗

剔除来自unknown的机构与作者文献文献——数据清洗 背景实例解决方法方法一: 使用专门处理bibx文件的库方法二: 直接处理纯文本数据背景 有时在研究过程中,会遇到不同类型的文献,但是有些文献中的数据会有部分缺失,常见的比如机构,作者和年份等字段,因此为了使用科研工…

esxi配置使用以及虚拟机管理

vSphere Client安装和esxi主机 esxi配置 许可证 虚拟机管理 vSphere Client中创建、删除等虚拟机的管理。 vSphere Client中创建虚拟机并安装操作系统&#xff1b; 步骤1 创建虚拟机 密码&#xff1a;Tongxin2023 (1) 厚置备延迟置零 以默认的厚格式创建虚拟磁盘。创建过…

机器学习实现文本分类

传统的向量空间模型&#xff08;VSM&#xff09;假设特征项之间相互独立&#xff0c;这与实际情况是不相符的&#xff0c;为了解决这个问题&#xff0c;可以采用文本的分布式表示方式(例如 word embedding形式)&#xff0c;通过文本的分布式表示&#xff0c;把文本表示成类似图…

使用API有效率地管理Dynadot域名,重新提交域名转移密码

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

通用外设-红外遥控器(NEC协议)

目录 前言 一、前期的准备 1. 结构体 2. 中断 1.定时中断 2.外部中断&#xff08;下降沿中断&#xff09; 二、功能实现 1.时序说明 2.逻辑实现 3.代码实现 总结 前言 简单介绍红外遥控器的使用&#xff0c;可以正常使用&#xff0c;但是部分功能未启用&#xff0c;…

风险评估在应对网络安全威胁中扮演着重要的角色

如今&#xff0c;IT 安全专家面临各种重大威胁&#xff0c;从勒索软件、网络钓鱼&#xff0c;到对基础设施的攻击&#xff0c;再到对知识产权、客户数据的窃取&#xff1b;从不安全的供应链合作伙伴&#xff0c;再到组织内部人员的恶意行为。同时&#xff0c;随着云计算、远程工…

关于ASP.NET Core WebSocket实现集群的思考

前言 提到WebSocket相信大家都听说过&#xff0c;它的初衷是为了解决客户端浏览器与服务端进行双向通信&#xff0c;是在单个TCP连接上进行全双工通讯的协议。在没有WebSocket之前只能通过浏览器到服务端的请求应答模式比如轮询&#xff0c;来实现服务端的变更响应到客户端&…

【鹅厂摸鱼日记(二)】(生活篇)初到深圳的人情冷暖

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:重生之我在鹅厂摸鱼⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多知识   &#x1f51d;&#x1f51d; 摸鱼日记 1. 前言2. 鹅厂的人文关怀…

FFmpeg: 简易ijkplayer播放器实现--03UI界面设计

文章目录 UI设计流程图UI设计界面点击播放功能实现 UI设计流程图 UI设计界面 主界面 控制条 播放列表 画面显示 标题栏 设置界面 提示框 点击播放功能实现 槽函数实现&#xff1a; connect(ui->ctrlBarWind, &CtrlBar::SigPlayOrPause, this, &Main…

09 Php学习:数组和排序

数组概念 在PHP中&#xff0c;数组是一种复合数据类型&#xff0c;用于存储多个值。以下是关于PHP数组的详细解释&#xff1a; 索引数组&#xff1a;索引数组是最基本的数组类型&#xff0c;其中每个元素都有一个唯一的数字索引&#xff0c;从0开始递增。 关联数组&#xff…

1、Qt UI控件 -- qucsdk

前言&#xff1a;Qt编写的自定义控件插件的sdk集合&#xff0c;包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库&#xff0c;都是一些编译好的控件&#xff0c;可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…