代码随想录算法训练营第22天 | 235. 二叉搜索树的最近公共祖先 , 701.二叉搜索树中的插入操作 , 450.删除二叉搜索树中的节点

二叉树理论基础:

https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE

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

题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

思路:

遇到这个题目首先想的是要是能自底向上查找就好了,这样就可以找到公共祖先了。
后序遍历(左右中)就是天然的回溯过程,可以根据左右子树的返回值,来处理中节点的逻辑。
首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。 即情况一:
在这里插入图片描述
同时,题目强调:二叉树节点数值是不重复的,而且一定存在 q 和 p。
但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q§。 情况二:
在这里插入图片描述
其实情况一 和 情况二 代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。

因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本身就是 公共祖先的情况。
具体来说,可以在代码中,慢慢体会。

当左子树和右子树都返回上来,不为空的情况下,就找到了。反之哪边找到了,就把结果层层回溯,返回给头结点。
在这里插入图片描述

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        // 这一步会把情况2(公共祖先)也包含进去 直接返回root结点,不会再判断下面的了
        if(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;
        if(left == null && right!= null)    return right;
        if(left != null && right == null)   return left;
        // 都为空的情况
        return null;
    }

}

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

题目连接:https://leetcode.cn/problems/insert-into-a-binary-search-tree/

思路:

可以不考虑题目中提示所说的改变树的结构的插入方式。
只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了。
在这里插入图片描述
例如插入元素10 ,需要找到末尾节点插入便可,一样的道理来插入元素15,插入元素0,插入元素6,需要调整二叉树的结构么? 并不需要。

只要遍历二叉搜索树,找到空节点 插入元素就可以了,那么这道题其实就简单了。、

同时,搜索树是有方向了,可以根据插入元素的数值,决定递归方向。

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root == null){
            root = new TreeNode(val);
        }
        if(root.val < val)  root.right = insertIntoBST(root.right,val);
        if(root.val > val)  root.left = insertIntoBST(root.left,val);
        return root;
    }
}

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

题目链接:https://leetcode.cn/problems/delete-node-in-a-bst/

思路:

搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑。
(1)没找到删除的结点,遍历到空结点直接返回
(2)左右孩子都为空(叶子结点),直接删除节点, 返回NULL为根节点
(3)只有左孩子为空,或者只有右孩子为空,这个时候只需要让他的孩子直接补位,返回左/右孩子为根节点即可
(4)左右孩子都不为空,这个情况是最复杂的,这里看左子树和右子树都行,结果不是唯一的。这里我们将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,这样可以保证是在比他小一点点(最接近)的结点下,返回删除节点右孩子为新的根节点。

可以根据这个图来理解。
原数据:
在这里插入图片描述
删除后:
在这里插入图片描述
要删除的节点(元素7)的右孩子(元素9)为新的根节点。.
在这里插入图片描述

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        // 没找到的情况包含在这里
        if(root == null)    return root;
        if(root.val == key){
            // 左节点为空的情况
            if(root.left == null)
                return root.right;
            // 右节点为空的情况
            else if(root.right == null)
                return root.left;
            // 左不为空,右也不为空
            // 把右子树中最大的结点当做新的结点,把原来的左子树全都放在这个结点下
            else{
                TreeNode tmp = root.right;
                while(tmp.left!=null)
                    tmp = tmp.left;
                tmp.left = root.left;
                root = root.right;  // 原来的结点也要更新
                return root;
            }
        }

        if(root.val > key)  root.left = deleteNode(root.left,key);
        if(root.val < key)  root.right = deleteNode(root.right,key);
        return root;
    }
}

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

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

相关文章

vue3-内置组件-Transition

基于状态变化的过渡和动画&#xff08;常用&#xff09; 建议多看几遍~~。然后动手去写写&#xff0c;学编程只有多动手才能有感觉。 内置组件: 它在任意别的组件中都可以被使用&#xff0c;无需注册。 Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动…

AMH面板如何安装与公网远程访问本地面板界面

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Mac版Idea实用快捷键+使用技巧

快捷键 全局查找 shift command f 查找类(class) command o 查找classfilesymbolaction 点击两次shift 复制当前行 command d 自动代码提示 option enter 代码格式化 option command l 生成代码(构造函数、Getter/Setter方法、equals方法、hashCode方法、…

VLM 系列——Llava1.6——论文解读

一、概述 1、是什么 Llava1.6 是llava1.5 的升级暂时还没有论文等&#xff0c;是一个多模态视觉-文本大语言模型&#xff0c;可以完成&#xff1a;图像描述、视觉问答、根据图片写代码&#xff08;HTML、JS、CSS&#xff09;&#xff0c;潜在可以完成单个目标的视觉定位、名画…

这一年让我印象深刻的bug --外部接口请求失败问题

1 业务场景 我们有个需求是外部客户需要在我们系统创建一个账号。业务流程如下 但是我们运行一段时间后发现一个问题&#xff0c;有客户反创建客户账号时&#xff0c;提示账号已经存在&#xff0c;但是我们系统却查不到单号 2 问题分析 经分析报错来源于权限系统&#xff0c;我…

学习Spring的第十五天

spring aop动态代理开发 一、什么是动态代理 动态代理就是&#xff0c;在程序运行期&#xff0c;创建目标对象的代理对象&#xff0c;并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中&#xff0c;目标对象不变&#xff0c;代理对象中的方法是目标对象…

基于JavaWeb开发的火车售票系统[附源码]

基于JavaWeb开发的火车售票系统[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &#x1f4dd…

XCTF:3-1[WriteUP]

从题目中获取文件 使用file命令查看文件类型 修改后缀为.rar后进行解压缩 再次使用file命令查询该文件的类型 再次修改后缀为.pcap或者.pcapng 使用wireshark打开&#xff0c;直接搜索flag字样 在多个数据包里发现了flag.rar、flag.txt等文件 尝试使用http导出文件 有一个fl…

Sui上TVL突破5亿美元,位列DeFi榜单前十名和最活跃链前五名

2023年Sui上DeFi协议迅速增长&#xff0c;2024年这一势头仍在继续&#xff0c;根据DeFiLlama报告Sui上TVL近期超过5亿美元。在不到一年的时间里就达到这个金额&#xff0c;得益于Sui的突破性指标&#xff0c;比如其峰值TPS接近6,000。 Sui TVL突破5亿美元&#xff0c;登上DeFi…

超多制作模板的姓氏头像生成器微信小程序源码

超多制作模板的姓氏头像生成器微信小程序源码&#xff0c;这是一款姓氏头像制作小工具&#xff0c;内含丰富多样的模板提供制作。 以前的基本是固定位置生成&#xff0c;这款制作支持拖拽调整位置&#xff0c;自定义颜色&#xff0c;阴影等等。

第三百零八回

文章目录 1. 概念介绍2. 实现方法2.1 文字信息2.2 红色边框 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何实现密码输入框"相关的内容&#xff0c;本章回中将介绍如何在在输入框中提示错误.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们…

【 buuctf-另外一个世界】

flag 就隐藏在这一串二进制数中&#xff0c;可以利用在线工具转换得到 flag&#xff0c;本次讲一下用代码怎么转换。将二进制数转换成 ascii 字母&#xff0c;手写的话两种思路&#xff1a; 1.将二进制数四位一组先转成十六进制数&#xff0c;再将十六进制数两位一组&#xff…

L1-023 输出GPLT-java

输入样例&#xff1a; pcTclnGloRgLrtLhgljkLhGFauPewSKgt输出样例&#xff1a; GPLTGPLTGLTGLGLL 思路 设置一个GPLT的计数器 然后遍历的时候每次对计数器的个数减一 import java.io.*;public class Main {public static void main(String[] args) throws IOException {B…

ele-h5项目使用vue3+vite+vant4开发:第三节、自定义hooks-useToggle实现搜索页展示切换

需求分析 点击首页搜索框&#xff0c;出现搜索页点击搜索页,隐藏搜索页,展示首页新建搜索页组件实现效果 hooks介绍 理解 hooks 就是将去改变一个参数值时&#xff0c;页面也会更新对应的值的想法、抽象&#xff0c;用代码实现的地方 如何实现一个hooks 在src&#xff08;sour…

c++阶梯之类与对象(中)

目录 1.类的6个默认成员函数 2. 构造函数 2.1 构造函数概念的引出 2.2 构造函数的特性 3. 析构函数 3.1 析构函数的概念 3.2 特性 未使用构造与析构的版本 使用了构造与析构函数的版本 4. 拷贝构造函数 4.1 拷贝构造函数的概念 4.2 特性 结语 本节我们来认识…

Vue中keep-alive的作用、原理及应用场景

在进行Vue开发的过程中&#xff0c;我们经常会遇到需要进行组件缓存的场景&#xff0c;这时候Vue提供的keep-alive组件就派上了用场。keep-alive组件是Vue内置的一个抽象组件&#xff0c;它可以将其包裹的组件进行缓存&#xff0c;提高组件的性能&#xff0c;同时也可以节省服务…

Python学习路线 - Python高阶技巧 - 拓展

Python学习路线 - Python高阶技巧 - 拓展 闭包闭包注意事项 装饰器装饰器的一般写法(闭包写法)装饰器的语法糖写法 设计模式单例模式工厂模式 多线程进程、线程并行执行多线程编程threading模块 网络编程Socket客户端和服务端Socket服务端编程实现服务端并结合客户端进行测试 S…

使用Java实现HTTP持久连接:一次与网络的“长聊“

大家都知道&#xff0c;传统的HTTP连接就像是一次性的餐具&#xff0c;每发送一个请求&#xff0c;就得重新建立一个连接&#xff0c;然后快速用完就扔。这对于网络资源来说&#xff0c;简直就是一场"大肆挥霍"的派对。但幸好&#xff0c;我们有HTTP持久连接&#xf…

【字符串】字典树

字典树就是利用一个这样的树状结构&#xff0c;可以记录字符串有没有出现过 放个板子 int nxt[100000][26], cnt; bool st[100000]; // 该结点结尾的字符串是否存在 void insert(string s, int l) // 插入字符串&#xff0c;l是字符串长度 { int p 0;for (int i 0; i < …

BGP邻居故障检测

第一种情况:如果AR2和AR4采用直连建立邻居,则排查步骤如下: 1)在AR2和AR4上使用ping x.x.x.x命令检查AR2和AR4用于建立EBGP邻居关系的直连地址连通性是否正常。如果不能ping通。则需要使用二分法从网络层向下层逐层进行排查,首先检查接口地址及路由的可达性,修改完成后,如…