首页 > 其他分享 >力扣---450. 删除二叉搜索树中的节点

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

时间:2023-05-25 11:25:07浏览次数:42  
标签:力扣 right 450 --- key null root 节点 left

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。
 

示例 1:

 

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。


示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点
示例 3:

输入: root = [], key = 0
输出: []
 

提示:

节点数的范围 [0, 104].
-105 <= Node.val <= 105
节点值唯一
root 是合法的二叉搜索树
-105 <= key <= 105
 

进阶: 要求算法时间复杂度为 O(h),h 为树的高度。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/delete-node-in-a-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


 

麻烦的地方在于删除后继续保持二叉搜索树的性质。

class Solution {
    public TreeNode deleteNode (TreeNode root, int key) {
        if (root == null) {
            return null;
        }
//        对根结点进行判断,避开父节点为 null 的情况。
        if (root.val == key) {
            if (root.left == null && root.right == null) {
                return null;
            } else if (root.left == null) {
                return root.right;
            } else if (root.right == null) {
                return root.left;
            }
            getLeftLeaf(root.right).left = root.left;
            return root.right;
        } else {
            dfs(root, null, key, true);
        }
        return root;
    }
//    @direction 该节点为父节点的左子树还是右子树,true 为左,false 为右。
private void dfs (TreeNode root, TreeNode parent, int key, boolean direction) {
//        不包含 key
        if (root == null) {
            return;
        }
        if (root.val > key) {
            dfs(root.left, root, key, true);
        } else if (root.val < key) {
            dfs(root.right, root, key, false);
        } else {
//             找到 key 所在节点
//            第一种情况:目标节点的左右节点都为 null
            if (root.left == null && root.right == null) {
                if (direction) {
                    parent.left = null;
                } else {
                    parent.right = null;
                }
//            第二种情况:目标节点的左右节点都不为 null,此时将目标节点的左子树放到右子树最左边的叶子节点,然后将该节点删除即可(参考第三,第四种情况)。
            } else if (root.left != null && root.right != null) {
                getLeftLeaf(root.right).left = root.left;
                if (direction) {
                    parent.left = root.right;
                } else {
                    parent.right = root.right;
                }
//            第三种情况:目标节点的左节点为 null,此时将右子树直接替代目标节点即可。
            } else if (root.left == null) {
                if (direction) {
                    parent.left = root.right;
                } else {
                    parent.right = root.right;
                }
//            第四种情况:目标节点的右节点为 null,此时将左子树直接替代目标节点即可。
            } else {
                if (direction) {
                    parent.left = root.left;
                } else {
                    parent.right = root.left;
                }
            }

        }
    }

//    寻找目标节点右子树最左边的节点。
    private TreeNode getLeftLeaf (TreeNode root) {
        if (root.left == null) {
            return root;
        } else {
            return getLeftLeaf(root.left);
        }
    }
}

 

标签:力扣,right,450,---,key,null,root,节点,left
From: https://www.cnblogs.com/allWu/p/17430603.html

相关文章

  • 自定义hook - 双击事件 - useDBClick
    1.问题:业务场景中同时需要单击、双击事件,但是原生的onDoubleClick触发双击的时候会同时触发单击事件;2.解决方案:封装一个自定义hook能独立地触发单击和双击事件;根据两次点击的间隔是否小于interval来判断触发单击双击事件;//useDBClick.tsimport{MutableRe......
  • Revit二次开发-Curveloop的放大和缩小
    在Revit二次开发工作中,或许会用对Curveloop的放大、缩小、偏移等操作。我们查阅开发手册就可以发现Curveloop这个类提供了Transform这个实例方法,有了这个方法我们对Curveloop进行一些操作,下面是一个简单的Demo,通过放大缩小创建了三块楼板。protectedoverrideResultExecute(Ext......
  • 一篇文章解密 - 如何在MyEclipse中使用JavaScript编写代码?
    MyEclipsev2022.1.0正式版下载MyEclipse技术交流群:742336981欢迎一起进群讨论JavaScript项目在MyEclipse2021及更高版本中,JavaScript支持对大多数JavaScript源代码都是开箱即用的——不需要特殊的JavaScriptEclipse项目或JavaScriptfacet。但是,我们建议使用jscon......
  • 论文解析 -- A Survey of Large Language Models
     什么是语言模型?生成式,完成语言接龙或填空Technically,languagemodeling(LM)isoneofthemajorapproachestoadvancinglanguageintelligenceofmachines.Ingeneral,LMaimstomodelthegenerativelikelihoodofwordsequences,soastopredictthepro......
  • 2P4M-ASEMI代理伟达原装单向可控硅2P4M
    编辑:ll2P4M-ASEMI代理伟达原装单向可控硅2P4M型号:2P4M品牌:韦达\WEIDA封装:TO-252正向电流:2A反向电压:600V引脚数量:3芯片个数:1芯片尺寸:漏电流:>10ua恢复时间:浪涌电流:30A包装方式:盘装封装尺寸:如图特性:单向可控硅工作结温:-40℃~150℃2P4M的电性参数:正向电流2A;反向电压6......
  • day 105 - javaBean
    javaBean是一种实体类JavaBean有特定的写法必须有一个无参构造属性必须私有化必须有对应的get,set方法一般用来和数据库字段做映射:ORMORM:对象关系映射表-->类字段-->属性行记录-->对象实现创建数据库,创建对应实体类 //实体类,和数据库中的表结构......
  • LINUX系列-网络篇
    一网卡配置配置文件位置:/etc/sysconfig/network-scripts/ifcfg-eth01.DEVICE=eth0网卡名字2.HWADDR=00:0c:29:90:89:d9HWADDRHardWareAddress硬件地址MAC地址3.TYPE=Ethernet网络类型。以太网4.UUID=ae779ae6-044d-43d5-a33b-48c89e8de10e#UUID做到系统中独一......
  • sed -i -e什么意思
    在`sed`命令中,`-i`和`-e`是两个选项,用于在原始文件上进行直接编辑和指定编辑脚本。下面是它们的具体含义:-**`-i`选项:**`-i`选项用于在原始文件上进行直接编辑(in-placeediting)。它的作用是将`sed`命令的结果直接写回到原始文件中,而不是将输出发送到标准输出。使用`-i......
  • LINUX系列-服务器cpu和内存篇
    一系统内存过高排查方法1、使用top命令查看当前服务器上所有进行使用内存情况,可以使用shift+m按键,将进程按照内存使用情况排序。如若某个进程占用过多内存,使用kill<pid>终止该进程。2、检查是否有内存泄漏情况。psaux--sort=-%mem该命令可按照内存使用率高低进行......
  • vue---属性绑定:多个判断条件/class/style
    我们在做VUE项目开发的时候,经常会遇到需要绑定多个判断条件,多个class,多个style的情况,下面就整理一下:一、绑定多个判断条件二、绑定多个class1、绑定一个类名<div:class="{'active':isActive}"></div>或三元表达式:<div:class="isActive?'active':''"><......