二叉搜索树删除节点 动画演示
Day60:删除二叉搜索树的某个节点
1 题目
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
说明:要求算法时间复杂度为 O(h),h 为树的高度。
示例:
root = [5,3,6,2,4,null,7]
key = 3
5
/
3 6
/
2 4 7
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
5
/
4 6
/
2 7
另一个正确答案是 [5,2,6,null,4,null,7]。
5
/
2 6
4 7
2 分析过程
这道题被leetcode定为中等难度级别,实话讲确实属于这类级别,虽然思路不难,但是要想一次写出准确无误的代码,仍然不是一件简单的事情。如果你第一次做这道题能很快写出来,说明你对递归的理解、指针的掌控都达到了一定水平。
这道题的思路很straitforward,根据BST的性质,具体说来分为如下几种情况:
- 如果被删除节点关键码key小于当前根节点nodei.val,则问题规模直接降阶到左子树中
- 关键码key大于当前根节点nodei.val,直接到右子树中查找
- key等于当前根节点nodei.val,又分为4种情况: (1). nodei 无左右子树,摘除nodei节点,等于直接返回 None (2). nodei 仅有左子树,摘除nodei节点,等于直接返回 nodei.left (3). nodei 仅有右子树,摘除nodei节点,等于直接返回 nodei.right (4). nodei 都有左右子树,麻烦一点,方法之一:选择以nodei.right为根节点的树中最左侧节点,然后替换nodei
最后返回 nodei.
你看,上面的思路应该足够清晰,但是兑现为代码绝对又是另一回事。你首先要对递归有深刻的理解,其次像链表、二叉树等这类具备递归的数据结构,操作它们节点引用问题要时刻保持清醒,很容易出错。
3 如何写出代码
老规矩,这是我们的节点定义:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
解决方案对象的主方法,调用自定义方法self.__delNodei(root,key)
,这个方法的构思思路是这样:
第一个参数是BST树中的任意节点,因为BST严格满足递归,所以选取任意一个以节点nodei为根的树,删除里面等于key的节点。因此,这个功能一旦实现后,只需在参数赋值时赋值它为root即可。
class Solution(object):
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
return self.__delNodei(root,key)
所以关键是如何写出def __delNodei(self,nodei,key)
方法,下面我们一步一步分析。
根据上面的4种情况分析,我们在情况4时会用到找树的最左节点,为此先写出这个方法def __findMinNode(self,nodei)
:
# 找到以nodei为根节点树的最小值
def __findMinNode(self,nodei):
if not nodei.left:
return nodei
while nodei.left:
nodei = nodei.left
return nodei
这个比较简单,是链表、二叉树等递归结构的常规迭代思路,注意与向量表i=i+1迭代思路的区别。
先写出第一种大情况,比较简单。因为方法self.__delNodei(nodei.left,key)
实现删除等于key的节点后返回对nodei.left节点的引用,所以将nodei的left域指向它即可。
# 假定已经查询到nodei节点,删除后返回nodei节点的引用
def __delNodei(self,nodei,key):
if not nodei:
return None
#若满足下面条件,一定在左子树
if key < nodei.val:
nodei.left = self.__delNodei(nodei.left,key) # 删除后返回nodei.left节点的引用
以下面二叉搜索树删除值等于3的节点为例演示,伸入到左子树:
再写出第二种大情况,与上类似:
# 一定在右子树
elif nodei.val < key:
nodei.right = self.__delNodei(nodei.right,key)# 删除后返回nodei.right节点的引用
再写出第三种大情况,即找到了等于key节点,又分四种小情况:
被删除节点是叶子节点:直接返回None,就是摘除它了:
# nodei.val== key,删除nodei
else:
# 情况1:被删除节点是叶子节点
if not nodei.left and not nodei.right:
return None # 置为None
第二、三种小情况很相似,跳过被删除节点nodei,直接返回nodei.left 或 node.right 即可:
# 情况2:被删除节点无右子树
if not nodei.right:
return nodei.left # 跳过nodei,返回指向nodei.left,相当于删除了nodei
# 情况3:被删除节点无左子树
if not nodei.left:
return nodei.right
最后一种小情况,大家直接看注释吧:
# 情况4:被删除节点左右子树都不为空
# 先找到右子树中最左节点,即右子树最小值节点
minNodei = self.__findMinNode(nodei.right)
nodei.val = minNodei.val
# 删除minNodei,同时返回nodei.right的引用,并赋值给nodei.right
## 切记:key已经不是__delNodei的参数key,而是我们找到的minNodei的val值
nodei.right = self.__delNodei(nodei.right,minNodei.val)
return nodei
上面代码,删除节点3的动画演示:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【LeetCode】把字符串 s 中的每个空格替换成““%20””day02
- bert加载数据代码
- python爬虫--看看虎牙女主播中谁颜值最高
- 基于maven+ssm的增删改查之maven环境的搭建
- (22)Bash环境变量
- maven之在eclipse中创建maven项目
- wiki百科之将词转换为索引表示
- 【LeetCode】找出数组中重复的数字day01
- pytorch实现的transformer代码分析
- 终于搞懂HashMap的源码了!!!
- (21)Bash用户自定义变量
- python实现支持向量机之具体实现
- Spring boot 集成apollo达到配置的热加载
- ApplicationContext 和beanFactory 和 factoryBean的区别以及联系
- pytorch中的nn.Embedding