leetcode450.删除二叉搜索树中的节点:迭代法巧用中间节点应对多场景删除
一、题目深度解析与BST特性剖析
在二叉搜索树(BST)中删除节点,需确保删除操作后树依然保持BST特性。题目要求我们根据给定的节点值key
,在BST中删除对应节点。BST的核心特性是左子树所有节点值小于根节点值,右子树所有节点值大于根节点值,这一特性为我们提供了高效定位和处理待删除节点的思路。删除节点时,由于节点在树中的位置不同,可能存在多种情况,合理利用BST特性判断场景,并通过中间节点辅助处理,是解决问题的关键。
二、迭代解法的完整代码与逻辑框架
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public TreeNode deleteNode(TreeNode root, int key) {if(root == null){return null;}TreeNode pre = root;TreeNode cur = root;while(cur != null){if(cur.val > key){pre = cur;cur = cur.left;}else if(cur.val < key){pre = cur;cur = cur.right;}else{if(cur == pre.left){pre.left = deleteOneNode(cur);break;}else if(cur == pre.right){pre.right = deleteOneNode(cur);break;}else{return deleteOneNode(cur);}}}return root;}public TreeNode deleteOneNode(TreeNode root){if(root == null){return root;}if(root.left == null){return root.right;}else if(root.right == null){return root.left;}else{TreeNode cur = root.right;while(cur.left != null){cur = cur.left;}cur.left = root.left;root = root.right;return root;}}
}
核心变量与逻辑设计
pre
与cur
节点:pre
节点用于记录cur
节点的父节点,在找到待删除节点后,pre
可辅助将删除节点后的子树重新连接到原树中。cur
节点用于遍历树,通过比较cur.val
与key
,在BST中定位待删除节点。
deleteOneNode
方法:专门处理删除节点的具体逻辑,针对待删除节点的不同子树情况进行处理,确保删除后树的BST特性不变。
三、核心问题解析:场景判断与中间节点的作用
1. 利用BST特性定位待删除节点
在BST中,我们可以通过比较节点值与key
的大小关系,高效定位待删除节点。代码中通过while
循环实现:
while(cur != null){if(cur.val > key){pre = cur;cur = cur.left;}else if(cur.val < key){pre = cur;cur = cur.right;}else{// 找到待删除节点,进入处理逻辑}
}
当cur.val > key
时,根据BST特性,待删除节点必然在cur
的左子树中,因此将pre
更新为cur
,cur
移动到其左子树继续查找;当cur.val < key
时,待删除节点在cur
的右子树中,同样更新pre
和cur
继续查找;若cur.val == key
,则找到了待删除节点,进入后续处理逻辑。
2. 多场景判断与中间节点辅助处理
找到待删除节点后,根据其在树中的位置以及子树情况,存在多种处理场景:
- 待删除节点是父节点的左子节点:
if(cur == pre.left){pre.left = deleteOneNode(cur);break;
}
此时,通过pre
节点找到待删除节点的父节点,将父节点的左子树更新为删除cur
节点后的子树,即调用deleteOneNode(cur)
的返回结果。
- 待删除节点是父节点的右子节点:
else if(cur == pre.right){pre.right = deleteOneNode(cur);break;
}
与左子节点情况类似,将父节点的右子树更新为删除cur
节点后的子树。
- 待删除节点是根节点:
else{return deleteOneNode(cur);
}
直接调用deleteOneNode(cur)
处理根节点的删除,并返回处理后的新根节点。
3. deleteOneNode
方法的场景处理
deleteOneNode
方法进一步针对待删除节点的子树情况进行处理:
- 待删除节点无左子树:
if(root.left == null){return root.right;
}
此时,直接返回其右子树,将右子树连接到原父节点对应位置,这样既保证了删除节点,又维持了BST特性。
- 待删除节点无右子树:
else if(root.right == null){return root.left;
}
与无左子树情况类似,返回其左子树连接到原父节点对应位置。
- 待删除节点左右子树均存在:
else{TreeNode cur = root.right;while(cur.left != null){cur = cur.left;}cur.left = root.left;root = root.right;return root;
}
此时,需要找到待删除节点右子树中的最小节点(最左节点),将原左子树连接到该最小节点的左子树位置,然后将待删除节点的右子树作为新的子树返回。这样操作后,树依然保持BST特性,因为右子树最小节点大于原左子树所有节点,小于原右子树其他节点。
四、迭代流程深度模拟:以具体示例BST展示操作过程
假设我们有如下BST:
5/ \3 6/ \ \2 4 7
我们要删除节点值为3
的节点。
- 定位待删除节点:
- 初始时,
pre = root = 5
,cur = root = 5
。 - 因为
3 < 5
,所以pre = 5
,cur = cur.right = 3
。此时找到了待删除节点,且cur
是pre
的左子节点。
- 初始时,
- 处理删除节点:
- 由于
cur
是pre
的左子节点,执行pre.left = deleteOneNode(cur)
。 - 进入
deleteOneNode
方法,cur
节点左右子树均存在,找到cur
右子树的最小节点4
,将cur
的左子树2
连接到4
的左子树,即4.left = 2
,然后返回cur
的右子树,也就是4
。 - 此时
pre.left
(即5.left
)更新为4
,完成节点删除操作。
- 由于
- 删除后的BST:
5/ \4 6/ \2 7
五、算法复杂度分析
1. 时间复杂度
在定位待删除节点过程中,每次比较都能排除一半的子树,时间复杂度为O(h),其中h为树的高度。在平衡BST中,h = logn(n为节点数),时间复杂度为O(logn);在最坏情况下,树退化为链表,h = n,时间复杂度为O(n)。处理删除节点的操作,无论是哪种场景,都只涉及常数次指针操作,时间复杂度也为O(h)。因此,整体时间复杂度为O(h)。
2. 空间复杂度
算法使用了常数个额外的指针变量(pre
和cur
等),空间复杂度为O(1),不随树的规模变化而增加。
六、核心技术点总结:迭代删除的关键要素
- BST特性的深度运用:通过节点值大小比较,高效定位待删除节点,减少不必要的遍历。
- 多场景判断策略:根据待删除节点在树中的位置以及子树情况,细致区分不同场景,分别进行处理,确保删除操作的正确性。
- 中间节点的巧妙辅助:
pre
和cur
节点的设置,在定位和处理删除节点过程中发挥了重要作用,使子树的重新连接更加清晰和高效。
七、常见误区与优化建议
1. 错误的指针操作
在处理子树连接时,容易出现指针指向错误,例如在将右子树最小节点与原左子树连接时,误将右子树最小节点的右子树连接原左子树。应仔细确认指针操作,确保连接关系正确。
2. 忽略边界情况
在代码中,虽然对空树情况进行了处理,但在实际应用中,还需注意其他边界情况,如树中只有一个节点时的删除操作,确保代码的健壮性。
3. 优化建议
可以考虑使用更简洁的代码结构,减少重复逻辑,例如将deleteOneNode
方法中的部分逻辑提取为公共方法,提高代码的复用性和可读性。同时,在性能要求较高的场景下,可结合更复杂的数据结构或算法进一步优化删除操作的效率。
通过以上对迭代法删除二叉搜索树节点的详细分析,我们深入理解了如何利用BST特性和中间节点,高效、准确地处理删除操作。这种方法在实际应用中具有重要的参考价值,能够帮助我们更好地解决类似的树结构处理问题。
相关文章:
leetcode450.删除二叉搜索树中的节点:迭代法巧用中间节点应对多场景删除
一、题目深度解析与BST特性剖析 在二叉搜索树(BST)中删除节点,需确保删除操作后树依然保持BST特性。题目要求我们根据给定的节点值key,在BST中删除对应节点。BST的核心特性是左子树所有节点值小于根节点值,右子树所有…...

java虚拟机2
一、垃圾回收机制(GC) 1. 回收区域:GC主要回收堆内存区域。堆用于存放new出来的对象 。程序计数器、元数据区和栈一般不是GC回收的重点区域。 2. 回收单位:GC以对象为单位回收内存,而非字节。按对象维度回收更简便&am…...
自监督软提示调优:跨域NLP新突破
自监督的软提示调优方法(SPSS) 这篇论文提出了一种基于自监督的软提示调优方法(SPSS),用于无监督领域自适应。其核心目标是通过挖掘源域和目标域的内部知识,解决传统提示调优在跨域场景中依赖通用知识、模板生成低效的问题。 一、核心实现原理 1. 自监督分层聚类优化(…...

Pydantic 学习与使用
Pydantic 学习与使用 在 Fastapi 的 Web 开发中的数据验证通常都是在使用 Pydantic 来进行数据的校验,本文将对 Pydantic 的使用方法做记录与学习。 **简介:**Pydantic 是一个在 Python 中用于数据验证和解析的第三方库,它现在是 Python 使…...

PCB设计教程【入门篇】——电路分析基础-基本元件(二极管三极管场效应管)
前言 本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理、 目录 前言 1.二极管 1.发光…...

能按需拆分 PDF 为多个文档的工具
软件介绍 彩凤 PDF 拆分精灵是一款具备 PDF 拆分功能的软件。 功能特点 PDF 拆分功能较为常见,很多 PDF 软件都具备,例如 DC 软件提取 PDF 较为方便,但它不能从一个 PDF 里提取出多个 PDF。据印象,其他 PDF 软件也似乎没有能从…...

Apifox 5 月产品更新|数据模型支持查看「引用资源」、调试 AI 接口可实时预览 Markdown、性能优化
Apifox 新版本上线啦! 看看本次版本更新主要涵盖的重点内容,有没有你所关注的功能特性: 自动解析 JSON 参数名和参数值调试 AI 接口时,可预览 Markdown 格式的内容性能优化:新增「实验性功能」选项 使用独立进程执行…...

LiveGBS海康、大华、宇视、华为摄像头GB28181国标语音对讲及语音喊话:摄像头设备与服务HTTPS准备
LiveGBS海康、大华、宇视、华为摄像头GB28181国标语音对讲及语音喊话:摄像头设备与服务HTTPS准备 1、背景2、准备工作2.1、服务端必备条件(注意事项)2.2、语音对讲设备准备2.2.1、大华摄像机2.2.2、海康摄像机 3、开启音频并开始对讲4、相关问…...

Sqlalchemy 连mssql坑
连接失败: (pyodbc.OperationalError) (08001, [08001] [Microsoft][ODBC Driver 17 for SQL Server]SSL Provider: [error:0A00014D:SSL routines::legacy sigalg disallowed or unsupported] (-1) (SQLDriverConnect)) (Background on this error at: https://sqlalche.me/e/…...
Prompt Engineering 提示工程介绍与使用/调试技巧
1. 介绍 Prompt Engineering 是一种人工智能(AI)技术,它通过设计和改进 AI 的 prompt 来提高 AI 的表现。Prompt Engineering 的目标是创建高度有效和可控的 AI 系统,使其能够准确、可靠地执行特定任务。 如果你从来没有使用过Pr…...

LLaMaFactory - 支持的模型和模板 常用命令
一、 环境准备 激活LLaMaFactory环境,进入LLaMaFactory目录 cd LLaMA-Factoryconda activate llamafactory 下载模型 #模型下载 from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2.5-0.5B-Instruct) 二、启动一个 Qwen3-0.6B…...

大模型深度学习之双塔模型
前言 双塔模型(Two-Tower Model)是一种在推荐系统、信息检索和自然语言处理等领域广泛应用的深度学习架构。其核心思想是通过两个独立的神经网络(用户塔和物品塔)分别处理用户和物品的特征,并在共享的语义空间中通过相…...
MySQL 8主从同步实战指南:从原理到高可用架构落地
MySQL 8主从同步实战指南:从原理到高可用架构落地 本文将用3000字深度解析MySQL 8主从复制机制,配合全流程部署指南及电商平台实战案例,助你构建高性能数据库集群 一、主从复制核心原理剖析 1.1 复制架构全景图 #mermaid-svg-vdts3hTIyCtz4byk {font-family:"trebuche…...

瑞数6代jsvmp简单分析(天津电子税x局)
国际惯例 今天帮朋友看一个gov网站的瑞数加密(天津电子税x局) 传送门(登陆入口界面) 瑞数6特征 1.服务器会发两次包,第一次响应状态码为412,第二次响应状态码为200。 2.有三重debugger,其中有…...
缓存架构方案:Caffeine + Redis 双层缓存架构深度解析
在高并发、低延迟的现代互联网系统中,缓存是提升系统性能和稳定性的重要手段。随着业务复杂度的增长,单一缓存方案(如仅使用Redis或仅使用本地缓存)已难以满足高性能与一致性需求。 本文将围绕 Caffeine Redis 的双层缓存架构展…...
AI笔记 - 模型调试 - 调试方式
模型调试方式 基础信息打印模型信息计算参数量和计算量过滤原则profile方法get_model_complexity_info方法FlopCountAnalysis方法 基础信息 # 打印执行的设备数量:device_count:1 print(f"device_count:{torch.cuda.device_count()}")# 打印当前网络执行…...

榕壹云物品回收系统实战案例:基于ThinkPHP+MySQL+UniApp的二手物品回收小程序开发与优化
摘要:本文深入解析了一款基于ThinkPHPMySQLUniApp框架开发的二手物品回收小程序——榕壹云物品回收系统的技术实现与商业价值。通过剖析项目背景、核心技术架构、功能特性及系统优势,为开发者与潜在客户提供全面的参考指南,助力资源循环利用与…...

《软件工程》第 9 章 - 软件详细设计
目录 9.1 详细设计的任务与过程模型 9.2 用例设计 9.2.1 设计用例实现方案 9.2.2 构造设计类图 9.2.3 整合并优化用例实现方案 9.3 子系统设计 9.3.1 确立内部设计元素 9.3.2 导出设计类图 9.4 构件设计 9.5 类设计 9.5.1 精化类间关系 9.5.2 精化属性和操作 9.5.…...

WebVm:无需安装,一款可以在浏览器运行的 Linux 来了
WebVM 是一款可以在浏览器中运行的Linux虚拟机。不是那种HTMLJavaScript模拟的UI,完全通过HTML5/WebAssembly技术实现客户端运行。通过集成CheerpX虚拟化引擎,可直接在浏览器中运行未经修改的Debian系统。 Stars 数13054Forks 数2398 主要特点 完整 Lin…...

王树森推荐系统公开课 排序06:粗排模型
shared bottom 表示神经网络被所有特征共享。精排模型主要开销在神经网络,神经网络很大且很复杂。 每做一次推荐,用户塔只做一次推理。物品塔存放入向量数据库。 后期融合模型常用于召回,前期融合模型常用于精排。 物品塔短时间内比较稳…...
go并发编程| channel入门
channel 介绍 channel 是在 Go 的并发编程中使用的,这个工具的作用之一是 goroutine 之间通信(线程通信指的是多个线程之间通过共享数据或协作机制来协调操作,通常需要借助锁来保证同步)。Go 中推荐使用 channel(不同…...

PH热榜 | 2025-05-29
1. Tapflow 2.0 标语:将你的文档转化为可销售的指导手册、操作手册和工作流程。 介绍:Tapflow 2.0将各类知识(包括人工智能、设计、开发、营销等)转化为有条理且可销售的产品。现在你可以导入文件,让人工智能快速为你…...
详解GPU
详解GPU GPU(图形处理器)就像电脑里的 “图形小能手”,原本主要用来画画(渲染图形),现在还能帮忙干很多杂活(并行计算) 一、先认识 GPU 的 “钥匙”:驱动和开发工具 装驱…...
WPF【11_10】WPF实战-重构与美化(配置Material UI框架)
11-16 【UI美化】配置Material UI框架 三种比较主流的 UI 设计规范,分别是: 苹果的扁平化 UI 设计、安卓或者说谷歌 的 Material Design 以及微软的 Metro 风格。 这三种风格都极具特色,不过我们接下来将会使用的是 Material Design 。在 W…...
(自用)Java学习-5.16(取消收藏,批量操作,修改密码,用户更新,上传头像)
1. 取消收藏功能 前端实现: 用户点击“取消收藏”按钮时,前端通过变量status判断当前状态(0为未收藏,1为已收藏)。 发送AJAX请求到后端接口: 添加收藏:/favoriteise/addFavoriteise?pid商品ID…...

【Node.js】部署与运维
个人主页:Guiat 归属专栏:node.js 文章目录 1. Node.js 部署概述1.1 部署的核心要素1.2 Node.js 部署架构全景 2. 传统服务器部署2.1 Linux 服务器环境准备系统更新与基础软件安装创建应用用户 2.2 应用部署脚本2.3 环境变量管理2.4 Nginx 反向代理配置2…...

【Java Web】速通JavaScript
参考笔记:JavaWeb 速通JavaScript_javascript 速通-CSDN博客 目录 一、JavaScript快速入门 1. 基本介绍 2. JavaScript特点 3. JavaScript的引入方式(重要) 3.1 写在script标签中 3.2 以外部文件方式引入 二、JS的数据类型 1. 变量 2. 常用数据类型 3.特殊值 三、…...

TDengine 运维——巡检工具(安装前预配置)
背景 TDengine 的安装部署对环境系统有一定的依赖和要求,安装部署前需要进行环境预配置操作,本文档旨在说明安装前预配置工具在安装 TDengine 前对环境的预配置内容和工具的使用方法。 预配置工具使用方法 工具支持通过 help 参数查看支持的语法 Usa…...
C#索引器详解:让对象像数组一样被访问
索引器是C#中一个强大而实用的特性,它允许我们像访问数组一样访问类的成员。本文将全面介绍索引器的概念、语法、实现方式以及实际应用场景。 索引器基础概念 索引器(Indexer)是一组get和set访问器,与属性类似,但有以…...
机器学习课设
🎓 图像处理课程设计任务书 课程名称: 图像处理与模式识别 课设题目: 基于手工特征提取与传统机器学习方法的图像分类系统实现 一、课设目的 本课程设计旨在加深对图像处理与分类算法的理解,提升图像特征提取、传统机器学习模…...