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

news2024/10/7 10:23:25

系列文章目录


目录

  • 系列文章目录
  • 235. 二叉搜索树的最近公共祖先
    • ①递归法
      • 自己写的
      • 简洁版
    • ②迭代法
      • 不能这样写!
      • 正确写法
  • 701.二叉搜索树中的插入操作
    • ①递归法
    • ②迭代法
  • 450.删除二叉搜索树中的节点
    • 递归法


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

①递归法

自己写的

class Solution {
    TreeNode result;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //终止条件
        if (root == null || root == p || root == q) return root;
        if (root.val > p.val && root.val > q.val) {
            result = lowestCommonAncestor(root.left,p,q);
        } else if (root.val < p.val && root.val < q.val) {
            result = lowestCommonAncestor(root.right,p,q);
        } else {
            return root;
        }
        return result;
    }
}

简洁版

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);
        if(root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right,p,q);
        return root;
    }
}

②迭代法

不能这样写!

图片来自热心网友(大佬)

图片来自热心网友(大佬)

56的最近公共祖先是8而不是4

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

正确写法

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

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

①递归法

递归三部曲:

  1. 确定递归函数参数以及返回值:参数就是根节点指针,以及要插入元素,这里递归函数要不要有返回值呢?可以有,也可以没有,但递归函数如果没有返回值的话,实现是比较麻烦的,下面也会给出其具体实现代码。有返回值的话,可以利用返回值完成新加入的节点与其父节点的赋值操作
  2. 确定终止条件:终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
  3. 确定单层递归的逻辑
    • 如果root.val > val,说明应该将val插入左子树
      • 如果左子树不存在,将val作为root.left
      • 如果左子树存在,让左子树插入val
    • 如果root.val < val,说明应该将val插在右子树
      • 如果右子树不存在,将val作为root.right
      • 如果右子树存在,让右子树插入val
    • 返回插入val后的根节点,即左右子树插入节点后的根节点。
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        //终止条件
        if (root == null) return new TreeNode(val);

        if (root.val > val) {
            root.left=insertIntoBST(root.left, val);
        } else if (root.val < val) {
            root.right=insertIntoBST(root.right, val);
        }
        return root;
    }
}

②迭代法

迭代法遍历的过程中,需要记录一下当前遍历的节点的父节点,这样才能做插入节点的操作。用pre指针来记录上一个节点。

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val); // root为空,直接插入后返回
        TreeNode newRoot = root;//记录根节点
        TreeNode pre = null;// 这个很重要,需要记录上一个节点,否则无法赋值新节点

        while (root != null) {
            pre = root;
            if (root.val > val) {
                root = root.left;
            } else if (root.val < val) {
                root = root.right;
            }
        }
        //插入节点的操作
        if (pre.val > val) {
            pre.left = new TreeNode(val);
        } else {
            pre.right = new TreeNode(val);
        }
        return newRoot;
    }
}

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

二叉搜素树的性质:

左子树的所有val< 当前节点的val< 右子树的最小val= 右子树的最左边节点的val值。

递归法

递归三部曲:

  1. 确定递归函数参数以及返回值:通过递归返回值删除节点。
  2. 确定终止条件:删除当前节点的逻辑放在终止条件中,二叉搜索树中删除节点有以下五种情况:
    • 第一种情况:没找到删除的节点,遍历到空节点直接返回了;
    • 找到删除的节点
      • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点;
      • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点的右子树;
      • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点的左子树;
      • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点的右节点,作为删除后树的根节点。

:终止条件可以简化为:

        if (root == null) return root;//找不到要删除的节点,返回null
        if (root.val == key) {
            if (root.left == null) {
                return root.left;
            } else if (root.right == null) {
                return root.right;
            } else {
                TreeNode cur = root.right;
                while (cur.left != null) {
                    cur = cur.left;
                }
                cur.left = root.left;
                return root.right;
            }
        }

其中当要删除的节点的左右子树都不为空,一直循环找到右子树最左边的节点时,注意判断条件必须为while (cur.left != null) 而不能是while (cur != null) ,否则会在cur.left = root.left;这里报空指针异常。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //终止条件
        if (root == null) return root;//找不到要删除的节点,返回null
        if (root.val == key) {
            if (root.left == null && root.right == null) {//若为叶子节点
                return null;
            } else if (root.left != null && root.right == null) {//若左不为空右为空,返回左子树
                return root.left;
            } else if (root.left == null && root.right != null) {//若右不为空左为空,返回右子树
                return root.right;
            } else {//左右子树都不为空
                TreeNode cur = root.right;
                while (cur.left != null) {//一直循环找到右子树最左边的节点
                    cur = cur.left;
                }
                cur.left = root.left;//将要删除的节点的左子树拼接到右子树最左边的节点
                return root.right;//返回要删除的节点右子树
            }
        }
        // 如果root.val > key,证明要删除的节点应该会出现在左子树上,获取左子树删除key节点后的根节点作为新的左节点
        if (root.val > key) root.left = deleteNode(root.left, key);
        // 如果root.val < key,证明要删除的节点应该会出现在右子树上,获取右子树删除key节点后的根节点作为新的右节点
        if (root.val < key) root.right = deleteNode(root.right, key);
        // 返回删除key节点后的根节点
        return root;
    }
}

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

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

相关文章

【C+ +】第一个C+ + 项目的创建及namespace命名空间解释C++中的输入输出

目录 1.创建第一个c项目 1.1项目创建 1.2 .cpp源文件建立 1.3 第一个c程序hello world对比c语言hello world 2.命名空间 2.1 C关键字 2.2 命名空间---解决c语言中的命名冲突 2.2.1 namespace命名空间用法 2.2.2 &#xff1a;&#xff1a; 预作用限定符 2.2.3 命名空间的嵌套…

SCI一区 | Matlab实现BES-TCN-BiGRU-Attention秃鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现BES-TCN-BiGRU-Attention秃鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现BES-TCN-BiGRU-Attention秃鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程序…

rasa trian 报错解决---Project validation completed with errors.

rasa train 过程中&#xff1a;出现一下问题&#xff1b; Project validation completed with errors. 解决措施:python 3.10版本&#xff0c;rasa 3.6.19, 降低版本 pip3 install rasa3.5.17 -i https://pypi.tuna.tsinghua.edu.cn/simple成功解决

Vue3:Pinia简介及环境搭建

一、简介 Pinia是Vue3中的状态管理工具&#xff0c;类似与Vue2中的Vuex框架的作用 二、环境搭建 1、安装 npm install pinia2、配置 main.ts import {createApp} from vue import App from ./App.vue // 第一步&#xff1a;引入pinia import {createPinia} from piniacons…

SWM341系列应用(SFC和SPI应用)

SWM341系列 SFC和SPI应用 1、针对具有QSPI功能的SPI-NORFLASH&#xff0c;如需要使用4线数据为&#xff08;4BIT&#xff09;方式进行读操作&#xff0c;则需要将QE位使能&#xff0c;再开启4BIT的都操作指令后进行读取。 如没有开启QE位&#xff0c;则用4BIT进行读取的数据会有…

一维卷积神经网络的特征可视化

随着以深度学习为代表的人工智能技术的不断发展&#xff0c;许多具有重要意义的深度学习模型和算法被开发出来&#xff0c;应用于计算机视觉、自然语言处理、语音处理、生物医疗、金融应用等众多行业领域。深度学习先进的数据挖掘、训练和分析能力来源于深度神经网络的海量模型…

VUE——生命周期

概念&#xff1a; mounted:挂载 new Vue({el: "#x",data: {},methods: {},mounted() {}, }) 系统会自己调用&#xff0c;不需要我们调用。 案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><…

go包下载时报proxyconnect tcp: dial tcp 127.0.0.1:80: connectex错误的解决方案

一大早的GoLand就开始抽风了&#xff0c;好几个文件import都红了&#xff0c;于是我正常操作点击提示的sync&#xff0c;但是却报了一堆错&#xff1a; go: downloading google.golang.org/grpc v1.61.1 go: downloading google.golang.org/genproto v0.0.0-20240228224816-df9…

荣誉 | 人大金仓连续三年入选“金融信创优秀解决方案”

3月28日&#xff0c;由中国人民银行领导&#xff0c;中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布“第三期金融信创优秀解决方案”&#xff0c;人大金仓新一代手机银行系统解决方案成功入选&#xff0c;这也是人大金仓金融行业解决方案连续第三年获得用户认可。…

C++STL--排序算法

sort 使用快速排序,平均性能好O(nlogn),但最差情况可能很差O(n^2)。不稳定。 sort(v.begin(),v.end());//对v容器进行排序,默认升序 sort(v.begin(),v.end(),greater<int>());//降序排序对于支持随机访问的迭代器的容器&#xff0c; 都可以利用sort算法直接对其进行排序…

【漏洞复现】用友NC cloud uploadChunk 存在任意文件上传

0x01 阅读须知 “如棠安全的技术文章仅供参考&#xff0c;此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供…

软考 系统架构设计师系列知识点之云原生架构设计理论与实践(13)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之云原生架构设计理论与实践&#xff08;12&#xff09; 所属章节&#xff1a; 第14章. 云原生架构设计理论与实践 第3节 云原生架构相关技术 14.3.2 云原生微服务 1. 微服务发展背景 过去开发一个后端应用最为直接的方…

Appium如何自动判断浏览器驱动

问题&#xff1a;有的测试机chrome是这个版本&#xff0c;有的是另一个版本&#xff0c;怎么能让自动判断去跑呢&#xff1f;&#xff1f; 解决办法&#xff1a;使用appium的chromedriverExecutableDir和chromedriverChromeMappingFile 切忌使用chromedriverExecutableDir和c…

Scala第十八章节(Iterable集合、Seq集合、Set集合、Map集合以及统计字符个数案例)

Scala第十八章节 章节目标 掌握Iterable集合相关内容.掌握Seq集合相关内容.掌握Set集合相关内容.掌握Map集合相关内容.掌握统计字符个数案例. 1. Iterable 1.1 概述 Iterable代表一个可以迭代的集合, 它继承了Traversable特质, 同时也是其他集合的父特质. 最重要的是, 它定…

Python基础中易错点分享

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、方法当变量使用二、字符串使用1.输出一个长句子换行时&#xff0c;需要使用续行符“\”&#xff0c;否则报错2.字符串的格式化3.字符串格式化之format()函数4.浅…

肿瘤免疫反应瀑布图(源于The Miller Lab)

目录 数据格式 绘图 ①根据剂量 ②根据type ③根据治疗响应度 添加水平线 数据格式 肿瘤免疫响应数据 rm(list ls()) library(tidyverse) library(dplyr) library(knitr)#模拟数据 # We will randomly assign the two doses, 80 mg or 150 mg, to the 56 subjects Me…

【星城战记】揭秘成本控制奥秘 如何超越个人开店!

在电玩城行业的竞争中&#xff0c;成本控制和运营管理是决定企业盈利能力和生存空间的关键因素。许多投资者在选择投资项目时&#xff0c;往往忽视了这两个方面的重要性&#xff0c;导致在运营过程中遭遇重重困难。而【星城战记】作为行业内的佼佼者&#xff0c;以其卓越的成本…

ruoyi-vue-pro 前端vue js直接import导入本地文件使用方法

第一步&#xff0c;删除所有依赖&#xff0c;否则配置以后就会启动报错&#xff1a; 第二步配置对应的文件格式&#xff0c;我当前使用的是xml文件 config.module.rule(xml).test(/\.xml$/).use(xml-loader).loader(xml-loader).end();第三步重新安装所有依赖&#xff1a; …

编译 amd gpu 核心态驱动 rocm kmd linux kernel

AMD 开源了专门的 ROCm 的kmd Linux Kernel&#xff0c; 1,下载源代码 git clone --recursive https://github.com/ROCm/ROCK-Kernel-Driver.gitcd ROCK-Kernel-Driver/git checkout rocm-6.0.22,配置kernel cp -v /boot/config-$(uname -r) .config make menuconfig Graph…

Windows下Docker安装Kafka3+集群

编写 docker-compose.yaml 主要参照&#xff1a;https://www.cnblogs.com/wangguishe/p/17563274.html version: "3"services:kafka1:image: bitnami/kafka:3.4.1container_name: kafka1environment:- KAFKA_HEAP_OPTS-Xmx1024m -Xms1024m- KAFKA_ENABLE_KRAFTyes- K…