当前位置: 首页 > news >正文

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

目录

题目链接:

题目:

解题思路:

代码:

总结:


题目链接:

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

题目:

解题思路:

五种请情况:1未找到目标值,节点返回null

                2目标值节点的左右子节点都为null,返回null

                3目标值节点的左子树为null,返回右子树

                4目标值节点的右子树为null,返回左子树

                5都不为空,那就将左子树放在右子树的最左下面

代码:

/*** 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 root;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 node=root.right;while(node.left!=null) node=node.left;node.left=root.left;return root.right;}}else if(root.val<key){root.right=deleteNode(root.right,key);}else{root.left=deleteNode(root.left,key);}return root;}
}

二叉搜索树节点删除操作深度解析在二叉搜索树(Binary Search Tree,BST)的各类操作中,删除节点是相对复杂但又十分关键的操作。与插入和查找相比,删除需要考虑更多的情况,以确保删除节点后仍能维持二叉搜索树的特性。本文将对一段用于删除二叉搜索树中指定值节点的代码进行详细解析,带你深入理解其原理、执行流程及背后的逻辑。二叉搜索树删除节点的背景二叉搜索树的删除操作之所以复杂,是因为被删除的节点可能处于不同的位置,并且有不同的子节点情况。根据被删除节点的子节点数量,主要分为以下几种情况:被删除节点没有子节点(叶子节点):直接删除该节点即可。被删除节点只有一个子节点(左子节点或右子节点):用其子节点替代该节点的位置。被删除节点有两个子节点:需要找到一个合适的替代节点(通常是该节点右子树中的最小节点或左子树中的最大节点),将替代节点的值复制到当前节点,然后删除替代节点。代码整体结构java运行/**
 * 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 root;
        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 node=root.right;
                while(node.left!=null) node=node.left;
                node.left=root.left;
                return root.right;
            }
        }else if(root.val<key){
            root.right=deleteNode(root.right,key);
        }else{
            root.left=deleteNode(root.left,key);
        }
        return root;
    }
}
这段代码的核心是 deleteNode 方法,它接收二叉搜索树的根节点 root 和要删除的节点值 key,并返回删除节点后的二叉搜索树的根节点。关键代码逐行解析处理空树情况java运行if(root==null) return root;
这是递归的终止条件之一。如果当前根节点 root 为 null,说明树为空或者已经遍历到了空的位置,直接返回 root(即 null)。找到要删除的节点java运行if(root.val==key){
    // 处理不同子节点情况的代码
}
当当前根节点 root 的值等于要删除的 key 时,说明找到了要删除的节点,进入节点删除的处理逻辑。处理不同子节点情况叶子节点(没有子节点)java运行if(root.left==null&&root.right==null) return null;
如果要删除的节点是叶子节点(左子节点和右子节点都为 null),直接返回 null。这相当于将该节点从树中删除,因为其父节点的对应子节点引用会被更新为 null。只有左子节点java运行else if(root.left!=null&&root.right==null) return root.left;
如果要删除的节点只有左子节点,没有右子节点,那么返回其左子节点。这样,该节点的左子节点就会替代该节点的位置,维持二叉搜索树的结构。只有右子节点java运行else if(root.left==null&&root.right!=null) return root.right;
如果要删除的节点只有右子节点,没有左子节点,返回其右子节点,让右子节点替代该节点的位置。有两个子节点java运行else{
    TreeNode node=root.right;
    while(node.left!=null) node=node.left;
    node.left=root.left;
    return root.right;
}
如果要删除的节点有两个子节点,处理逻辑相对复杂:首先,找到该节点右子树中的最小节点(因为二叉搜索树右子树中的最小节点是大于当前节点值的最小元素,符合二叉搜索树的特性)。通过循环 while(node.left!=null) node=node.left; 来找到右子树中的最左节点,也就是最小节点。然后,将当前节点的左子树连接到找到的最小节点的左子节点上(node.left=root.left;)。最后,返回当前节点的右子节点,这样就用右子树中的最小节点替代了被删除的节点(因为最小节点的值已经通过后续的连接等操作间接起到了替代作用,而原来的右子节点成为新的子树结构的一部分)。递归查找要删除的节点java运行else if(root.val<key){
    root.right=deleteNode(root.right,key);
}
如果当前根节点 root 的值小于要删除的 key,根据二叉搜索树的特性,要删除的节点应该在右子树中。所以,递归调用 deleteNode 方法,参数为 root.right(当前根节点的右子节点)和 key,并将返回的结果赋值给 root.right。这样,在右子树中找到并删除指定节点后,更新当前根节点的右子节点引用。java运行else{
    root.left=deleteNode(root.left,key);
}
如果当前根节点 root 的值大于要删除的 key,同理,要删除的节点在左子树中。递归调用 deleteNode 方法,参数为 root.left 和 key,并将返回的结果赋值给 root.left,完成左子树中节点的查找和删除以及引用更新。返回根节点java运行return root;
在完成右子树或左子树的删除操作后,返回当前的根节点 root。这保证了每一层的根节点都能正确地将子树的引用传递给上一层,维护整个二叉搜索树的结构完整性。算法执行流程示例为了更好地理解代码的执行过程,我们通过一个具体的例子来模拟删除操作。假设初始的二叉搜索树结构如下(根节点值为 5,左子节点为 3,右子节点为 7;3 的左子节点为 2,右子节点为 4;7 的左子节点为 6,右子节点为 8):plaintext        5
       / \
      3   7
     / \ / \
    2  4 6  8
现在要删除值为 5 的节点(该节点有两个子节点)。调用 deleteNode(root, 5),其中 root 是值为 5 的节点。因为 root.val == key(5 == 5),进入有两个子节点的处理逻辑。找到右子树(值为 7 的节点)中的最小节点:从 7 开始,其左子节点是 6,6 没有左子节点,所以最小节点是 6。将当前节点(值为 5)的左子树(以 3 为根的子树)连接到最小节点 6 的左子节点上(node.left = root.left,此时 6 的左子节点变为以 3 为根的子树)。返回当前节点的右子节点(值为 7 的节点),作为新的根节点。最终,二叉搜索树的结构变为:plaintext        7
       / \
      6   8
     /
    3
   / \
  2   4
时间复杂度与空间复杂度时间复杂度该算法的时间复杂度为 \(O(h)\),其中 h 是二叉搜索树的高度。在理想情况下,二叉搜索树是平衡的,高度 \(h = \log n\)(n 为节点数),此时时间复杂度为 \(O(\log n)\)。但在最坏情况下,二叉搜索树可能退化为链表,此时高度 \(h = n\),时间复杂度为 \(O(n)\)。空间复杂度空间复杂度为 \(O(h)\),主要是由递归调用栈的深度决定的。递归调用的深度最多为二叉搜索树的高度 h,所以在理想情况下空间复杂度为 \(O(\log n)\),最坏情况下为 \(O(n)\)。总结这段用于删除二叉搜索树中指定值节点的代码,充分考虑了被删除节点的不同子节点情况,通过递归的方式,在找到要删除的节点后,根据其具体情况进行相应的处理,以维持二叉搜索树的特性。其核心思想是:利用二叉搜索树的特性递归查找要删除的节点,找到后根据子节点数量进行不同的删除和结构调整操作。理解这段代码,不仅有助于掌握二叉搜索树的删除操作,也能加深对递归算法和二叉搜索树特性的理解,为后续学习更复杂的树结构和操作(如平衡二叉树的调整)打下基础。

总结:

本文详细解析了二叉搜索树删除节点的操作,重点分析了五种不同情况的处理逻辑:空节点、叶子节点、单左/右子树节点、双子树节点。通过递归实现,代码将目标节点的左子树连接到右子树的最小节点下方,确保删除后仍保持BST特性。算法时间复杂度为O(h),空间复杂度为O(h),其中h为树高。该实现展现了BST删除操作的核心思想,为理解更复杂的树结构操作奠定了基础。

http://www.dtcms.com/a/392106.html

相关文章:

  • 实用工具:基于Python的图片定位导出小程序
  • 滚珠螺杆在工业机器人关节与线性模组的智能控制
  • 【AI】coze的简单入门构建智能体
  • Python数据分析:函数定义时的装饰器,好甜的语法糖。
  • Java数据结构——包装类和泛型
  • 【C++进阶】C++11的新特性 | 列表初始化 | 可变模板参数 | 新的类功能
  • 广东省省考备考(第一百零三天9.20)——言语(强化训练)
  • 面试编程题(四)
  • OpenHarmony之充电振动定制
  • 前端单元测试入门:使用 Vitest + Vue 测试组件逻辑与交互
  • 泛英国生物样本库全基因组关联分析
  • 【LeetCode 每日一题】2785. 将字符串中的元音字母排序
  • 游戏开发中的友好提示,错误信息,异常描述等数据管理的必要性
  • 总线协议(Bus Protocol)如何支持总线错误条件?
  • simuilink 中的引用模型(reference model)的作用? 它和子系统的区别? 如何生成引用模型?
  • HTML+JS实现table表格和鼠标移入移出效果
  • windows11用Qt6自带的mingw编译OSGEarth(自用记录)
  • 仓颉编程语言青少年基础教程:泛型(Generic)和区间(Range)类型
  • 原码反码补码------相关理解
  • 【Python】字典
  • 玩转deepseek之海报生成器
  • C++强制类型转换和I/O流深度解析
  • Transformer 和 MoE
  • Python基础 7》数据类型_元组(Tuple)
  • AI大模型入门第四篇:借助RAG实现精准用例自动生成!
  • leetcode 198 打家劫舍问题,两个dp数组->一个dp数组
  • 嵌入式ARM架构学习8——串口
  • Motion-sensor基础应用
  • 今日行情明日机会——20250919
  • 跟着Carl学算法--动态规划【7】