【算法练习Day19】二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点

news2024/11/20 13:27:24

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 二叉搜索树的最近公共祖先
  • 叉搜索树中的插入操作
  • 删除二叉搜索树中的节点
  • 总结:

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

235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)

看了题解,发现这道题与上一期相似的题的区别是,普通二叉树的查找最近公共节点,我们需要从二叉树的底部向上面遍历处理节点,而二叉搜索树,由于它自身拥有特定的排列顺序的缘故,我们要从上到下顺序的遍历处理节点,这一点上处理节点的顺序是不同的。我们根据搜索树的特征,将我们要查找的节点对应的值,与现在处在的节点值作比较,如果要查找的值大那么向右子树寻找,如果小向左子树递归

class Solution {
public:
    TreeNode* traversal(TreeNode* cur,TreeNode* p,TreeNode* q)
    {
        if(cur==NULL)
        {
            return cur;
        }
        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;

    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root,p,q);
    }
};

代码比求普通二叉树略简短一些。递归通过对left和right的判断而看是否找到了p,q其中之一,向上返回,我们将处在p和q中间的第一次遇到的节点直接返回上去,因为第一次遍历到的那个p和q中间的节点一定处在p和q子树的中间节点,如果它再向左或者向右子树递归,那么就一定会错过p或者q中的其中一个。这就是为什么我们遇到数值在其中间直接返回,这也是根据了搜索树的特性。

叉搜索树中的插入操作

701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

二叉搜索树中的插入操作,是略有理解难度的。起初在做这道题时,我们可能会被题目实例中的可以以多种答案提交而搞懵,有直接插入的,还有改变了二叉树结构插入进去的。这里我们需要明白,我们插入的任何节点都可以直接插入到该二叉搜索树的叶子节点处,也就是说不必要改变树的结构,因为改变树的结构的代码实现起来是有一些困难的。不理解为什么要插入的任何节点都可以在叶子节点插入的可以自行模拟一下。这里不必担心要插入的节点会和原二叉树某些节点值1相同,题目已经明确告诉了。

class Solution {
public:
    TreeNode* parent;
    void traversal(TreeNode* cur,int val)
    {
        if(cur==nullptr)
        {
            TreeNode* node=new TreeNode(val);
            if(val>parent->val)
            {
                parent->right=node;
            }
            else
            {
                parent->left=node;
            }
            return;
        }
        parent=cur;
        if(cur->val>val)
        {
            traversal(cur->left,val);
        }
        if(cur->val<val)
        {
            traversal(cur->right,val);
        }
        return;
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        parent=new TreeNode(0);
        if(root==nullptr)
        {
            root=new TreeNode(val);
        }
        traversal(root,val);
        return root;
    }
};

起初写代码时候,我是又自定义了一个void类型的函数,但是看了题解发现那样做很麻烦,直接在主函数上改动,是本题的最优解,当我们遍历到空的时候也就是找到了我们要插入的地点了,我们就直接原地创建一个节点然后返回上去,返回到上一层让上一层的节点链接我们要插入进去的节点即可。

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==NULL){
            TreeNode*node=new TreeNode(val);
            return node;
        }
        if(root->val>val){
            root->left=insertIntoBST(root->left,val);
        }
        if(root->val<val){
            root->right=insertIntoBST(root->right,val);
        }
        return root;
    }
};

这道题的向上递归逻辑就是,一层链接一层,由于我们没有改动二叉搜索树的结构,但是我觉得最好也要清楚,递归是如何一层一层向上返回的,它是每一次向上返回本层的节点,连接到上一层的left或者right处,当全部返回了之后,再把最开始的根节点root返回上去,作为返回值。

删除二叉搜索树中的节点

450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

删除二叉树的节点面临着改变二叉树的结构,而无法避免。所以该类型题是较有难度的,删除二叉搜索的某节点,大致分为几种情况:要删除的节点并不在该二叉树中,删除的是叶子节点,删除的节点有左子树但是没有右子树,有右子树但没有左子树,最后一种情况是左右子树都有,其中最后一种是最复杂的。

找不到该节点我们可以直接向上返回,不对该二叉树做任何的改动,如果是叶子节点那么我们将null返回到上一层,让链接目标节点的节点某一方向指向空,这时候我们就直接把它从二叉树上取了下来,中间的两者,都是让上一层链接我们要删除的节点的不为空的子树部分,直接连接上去就可以了,避免都结构的改动。最后一种,我们需要向上一层返回的是:该节点右子树的最左子树链接要删除节点的左子树。因为我们要删除的节点的右子树节点一定都比我们的要删除的左子树节点值要大,而它右子树的最左侧子树的值应该是略大于要删除的节点,这样我们就只是在我们删除的节点的右子树的最左侧叶子节点处插入了一本来就有序的左子树,这样的改动最大限度的减小了结构处理的困难性。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root==nullptr)
        {
            return root;
        }
        if(root->val==key)
        {
            if(root->left==nullptr&&root->right==nullptr)
            {
                delete root;
                return nullptr;
            }
            else if(root->left==nullptr)
            {
                auto retNode=root->right;
                delete root;
                return retNode;
            }
            else if(root->right==nullptr)
            {
                auto retNode=root->left;
                delete root;
                return retNode;
            }
            else
            {
                TreeNode* cur=root->right;
                while(cur->left!=nullptr)
                {
                    cur=cur->left;
                }
                cur->left=root->left;
                TreeNode* tmp=root;
                root=root->right;
                delete tmp;
                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/1088546.html

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

相关文章

MS5611的ZYNQ驱动试验之一 分析

0&#xff0c;MS5611框图 1&#xff0c;原理图 项目需要用到MS5611气压计模块&#xff0c;原理图很简单明了&#xff0c;如下&#xff1a; 这里PS接GND是SPI接口模式&#xff0c;PS接VDD是I2C接口模式。我在设计原理图时候直接设置成了SPI模式&#xff0c;当然这个SPI不是纯粹意…

ubuntu 22.04.3 live server图文安装流程

备注&#xff1a;以下操作全用键盘&#xff0c;tab切换&#xff0c;enter确认&#xff0c;方向键移动&#xff1b; 一、安装操作系统 1、 选择安装&#xff0c;第一个&#xff1b; 2、选择语言&#xff0c;这里只能选择英语&#xff0c;无中文&#xff1b; 3、继续而不更新 4、…

springcloud笔记(7)-限流降级Sentinel

官方文档&#xff1a;概述 | Spring Cloud Alibaba basic-api-resource-rule | Sentinel (sentinelguard.io) Sentinel是SpringCloudAlibaba的组件。 sentinel的功能 introduction | Sentinel 流量控制 熔断降级&#xff1a;降低调用链路中的不稳定资源 系统负载保护&am…

什么是接口自动化?为什么要做?和怎么做接口自动化?

服务端接口测试介绍 什么是服务端&#xff1f; 一般所说的服务端是指为用户在 APP 或 PC 使用的互联网功能提供数据服务的背后的一切。以天猫精灵智能音箱系列的产品链路为例&#xff0c;服务端便是网关&#xff08;包括网关在内&#xff09;之后的链路。 什么是接口&#xf…

数据结构—— AVL树

&#xff08;一&#xff09; 基础补充 二叉搜索树(BST) 定义&#xff1a; 二叉搜索树&#xff08;Binary Search Tree&#xff09;&#xff0c;简写BST&#xff0c;是满足某些条件的特殊二叉树。任何一个节点的左子树上的点&#xff0c;都必须小于当前节点。任何一个…

java split分割去掉空值

代码如下&#xff1a; public static void main(String[] args) {String dataString "#01#02#03#00#05#434";String[] infos Arrays.stream(dataString.split("#")).filter(s -> !s.isEmpty()).toArray(String[]::new);//投向领域IDString[] infos2 d…

深度学习-房价预测案例

1. 实现几个函数方便下载数据 import hashlib import os import tarfile import zipfile import requests#save DATA_HUB dict() DATA_URL http://d2l-data.s3-accelerate.amazonaws.com/def download(name, cache_diros.path.join(.., data)): #save"""下载…

独立站活动怎么复盘,做独立站需要掌握哪些?-站斧浏览器

独立站的活动形式多种多样&#xff0c;可以通过推出抽奖活动、举办线下活动或者利用社交媒体平台来增加用户互动和参与度。但是要做好一个独立站&#xff0c;除了活动形式&#xff0c;还需要掌握设计能力、编程技术、SEO知识和内容创作能力。 独立站活动怎么复盘&#xff1f; …

学习编程-先改变心态

编程失败的天才 林一和我很久以前就认识了——我从五年级就认识他了。他是班上最聪明的孩子。如果每个人在家庭作业或考试准备方面需要帮助&#xff0c;他们都会去那里。 有趣的是&#xff0c;林一不是那种连续学习几个小时的孩子。 他的聪明才智似乎与生俱来&#xff0c;几乎毫…

Selenium八大定位策略实战,你会了么?

Selenium是一款非常强大的自动化测试工具&#xff0c;支持多种编程语言&#xff0c;如Java、Python等。在使用Selenium进行自动化测试时&#xff0c;定位元素是非常重要的一步&#xff0c;只有正确定位到元素才能进行后续的操作&#xff0c;如输入数据、点击按钮等。在Selenium…

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Radio

单选框&#xff0c;提供相应的用户交互选择项。该组件从API Version 8开始支持。无子组件。 一、接口 Radio(options: {value: string, group: string}) 从API version 9开始&#xff0c;该接口支持在ArkTS卡片中使用。 参数: 二、属性 除支持通用属性外&#xff0c;还支持以…

springBoot组件注册

springBoot组件注册 前言1、创建组件文件2、写属性3、生成get和set方法4、以前注册的方法5、现在注册的方法6、在启动文件查看7、多实例Scope("prototype")8、注册第三方包导入对应的场景启动器注册组件查看是否存在也可以通过Import(FastsqlException.class)导入但是…

文字雨特效

效果展示 CSS 知识点 简易实现云朵技巧text-shadow 属性的灵活运用filter 属性实现元素自动变色 实现页面布局 <div class"container"><div class"cloud"><h2>Data Clouds Rain</h2></div> </div>实现云朵 实现云…

什么是API网关?——驱动数字化转型的“隐形冠军”

什么是API网关 API网关&#xff08;API Gateway&#xff09;是一个服务器&#xff0c;位于应用程序和后端服务之间&#xff0c;提供了一种集中式的方式来管理API的访问。它是系统的入口点&#xff0c;负责接收并处理来自客户端的请求&#xff0c;然后将请求路由到相应的后端服…

代码随想录第14天 | ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 /*** param {number[]} nums* return {number}*/ var lengthOfLIS function(nums) {let dp Array(nums.length).fill(1);let result 1;for(let i 1; i < nums.length; i) {for(let j 0; j < i; j) {if(nums[i] > nums[j]) {dp[i] Math.max…

最新开源ThinkPHP6框架云梦卡社区系统源码/亲测可用(全新开发)

源码简介&#xff1a; 最新开源ThinkPHP6云梦卡社区系统源码&#xff0c;它是一款基于ThinkPHP 6框架开发的开源社区系统源码。该系统源码具有强大而稳定的后端架构&#xff0c;和简洁易操作的前端界面&#xff0c;能够给人们提供完整的社区功能和更具体的服务。 全新云梦卡社…

fiddler如何抓模拟器中APP的包

第一步&#xff1a;fiddler配置 1、打开fiddler&#xff0c;依次点击工具&#xff08;tools&#xff09;》选项&#xff08;options&#xff09; 2、进入HTTPS选项&#xff0c;先选中DecryptHTTPStraffic&#xff0c;再选中ignore server certificate errors (unsafe) 3、点击…

【战略合作】新的游戏合作伙伴来袭,CARV 助力 Aavegotchi 发展!

想象这样的一个世界&#xff0c;你的游戏成就不仅仅是徽章&#xff0c;而是你链上声誉的一部分&#xff01;我们的最新游戏合作伙伴 CARV 便遵循这样的愿景。CARV 与 Aavegotchi 达成合作&#xff0c;旨在将下一代游戏玩家引入 Web3 世界。 CARV 正在构建一个以游戏为核心的身…

【云计算】相关解决方案介绍

文章目录 1.1 云服务环境 Eucalyptus1.1.1 介绍1.1.2 开源协议及语言1.1.3 官方网站 1.2 开源云计算平台 abiCloud1.2.1 开源协议及语言1.2.2 官方网站 1.3 分布式文件系统 Hadoop1.3.1 开源协议及语言1.3.2 官方网站 1.4 JBoss云计算项目集 StormGrind1.4.1 开源协议及语言1.4…

C# 图像灰化处理方法及速度对比

图像处理过程中&#xff0c;比较常见的灰化处理&#xff0c;将彩色图像处理为黑白图像&#xff0c;以便后续的其他处理工作。 在面对大量的图片或者像素尺寸比较大的图片的时候&#xff0c;处理速度和性能就显得非常重要&#xff0c;下面分别用3种方式来处理图像数据&#xff0…