Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 448ccf4

Browse files
add LeetCode 450. 删除二叉搜索树中的节点
1 parent 22c68f4 commit 448ccf4

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL2Nob2NvbGF0ZTE5OTkvY2RuL2ltZy8yMDIwMDgyODE0NTUyMS5qcGc?x-oss-process=image/format,png)
2+
>仰望星空的人,不应该被嘲笑
3+
4+
## 题目描述
5+
给定一个二叉搜索树的根节点 **root** 和一个值 **key**,删除二叉搜索树中的 **key** 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
6+
7+
一般来说,删除节点可分为两个步骤:
8+
9+
首先找到需要删除的节点;
10+
如果找到了,删除它。
11+
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
12+
13+
示例:
14+
15+
```javascript
16+
root = [5,3,6,2,4,null,7]
17+
key = 3
18+
19+
5
20+
/ \
21+
3 6
22+
/ \ \
23+
2 4 7
24+
25+
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
26+
27+
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
28+
29+
5
30+
/ \
31+
4 6
32+
/ \
33+
2 7
34+
35+
另一个正确答案是 [5,2,6,null,4,null,7]。
36+
37+
5
38+
/ \
39+
2 6
40+
\ \
41+
4 7
42+
```
43+
44+
来源:力扣(LeetCode)
45+
链接:https://leetcode-cn.com/problems/delete-node-in-a-bst
46+
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
47+
48+
49+
50+
51+
## 解题思路
52+
对于这道题,我们必须先了解一下二叉搜索树(BST)的性质,如下:
53+
54+
BST性质
55+
- 中序遍历是升序
56+
- left小于当前节点,right大于当前节点
57+
- 左子树、右子树也要是BST
58+
59+
60+
了解了性质之后,我们知道要查找对应 `key` 值,可以与根节点进行比较,如果小于根节点,直接去左子树找就好了,如果大于根节点,直接去右子树找就好了。
61+
62+
而对于刚好等于根节点的话,我拿着大佬的图解来看看几种情况:
63+
64+
65+
第一种情况,如果删除节点仅有右孩子,直接指向右孩子
66+
![](https://img-blog.csdnimg.cn/20200924222416522.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQyOTcxOA==,size_16,color_FFFFFF,t_70#pic_center)
67+
第二种情况,如果删除节点仅有左孩子,直接指向左孩子
68+
![](https://img-blog.csdnimg.cn/2020092422242489.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQyOTcxOA==,size_16,color_FFFFFF,t_70#pic_center)
69+
第三种情况,如果删除节点左右孩子都有,那么我们按照题意可以有两种删除方法:
70+
71+
1 找到要删除节点左子树的最右边的节点,即前驱的最大值(由BST性质得到)替换当前 root 节点,然后删除这个前驱
72+
73+
2 找到要删除节点右子树的最左边的节点,即后继最小值(由BST性质得到)替换当前 root 节点,然后删除这个后继
74+
![](https://img-blog.csdnimg.cn/20200924222430454.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQyOTcxOA==,size_16,color_FFFFFF,t_70#pic_center)
75+
76+
77+
78+
参考 <a href="https://leetcode-cn.com/problems/delete-node-in-a-bst/solution/tu-jie-di-gui-shi-xian-shan-chu-bstzhong-de-jie-di/">lulu</a> 大佬图解
79+
80+
代码提供了两种解法,对于前两种情况处理是一样的,只是对于最后一种情况,可以删除前驱的最大值,或者删除后继的最小值。
81+
82+
**删除前驱的最大值代码**
83+
84+
```javascript
85+
/**
86+
* Definition for a binary tree node.
87+
* function TreeNode(val, left, right) {
88+
* this.val = (val===undefined ? 0 : val)
89+
* this.left = (left===undefined ? null : left)
90+
* this.right = (right===undefined ? null : right)
91+
* }
92+
*/
93+
/**
94+
* @param {TreeNode} root
95+
* @param {number} key
96+
* @return {TreeNode}
97+
*/
98+
var deleteNode = function (root, key) {
99+
if (!root) return null;
100+
// 判断值是否小于root,小于走左子树,大于走右子树
101+
if (key < root.val) {
102+
root.left = deleteNode(root.left, key);
103+
} else if (key > root.val) {
104+
root.right = deleteNode(root.right, key);
105+
} else {
106+
// 1.如果删除节点没有左右子树,直接删除即可
107+
if (!root.left && !root.right) {
108+
root = null;
109+
// 2.如果删除节点仅有左孩子,直接指向左孩子
110+
} else if (root.left && !root.right) {
111+
root = root.left;
112+
// 3.如果删除节点仅有右孩子,直接指向右孩子
113+
} else if (!root.left && root.right) {
114+
root = root.right;
115+
} else {
116+
// 4.如果左右孩子都有,本代码采用方式是将前驱的最大值替换root的值
117+
let last = root.left;
118+
while (last.right) {
119+
last = last.right;
120+
}
121+
root.val = last.val;
122+
// 然后删除这个前驱最大值节点即可
123+
root.left = deleteNode(root.left, last.val);
124+
}
125+
}
126+
return root;
127+
};
128+
```
129+
130+
131+
**删除后继的最小值代码**
132+
133+
```javascript
134+
/**
135+
* Definition for a binary tree node.
136+
* function TreeNode(val, left, right) {
137+
* this.val = (val===undefined ? 0 : val)
138+
* this.left = (left===undefined ? null : left)
139+
* this.right = (right===undefined ? null : right)
140+
* }
141+
*/
142+
/**
143+
* @param {TreeNode} root
144+
* @param {number} key
145+
* @return {TreeNode}
146+
*/
147+
var deleteNode = function (root, key) {
148+
if (!root) return null;
149+
// 判断值是否小于root,小于走左子树,大于走右子树
150+
if (key < root.val) {
151+
root.left = deleteNode(root.left, key);
152+
} else if (key > root.val) {
153+
root.right = deleteNode(root.right, key);
154+
} else {
155+
// 1.如果删除节点没有左右子树,直接删除即可
156+
if (!root.left && !root.right) {
157+
root = null;
158+
// 2.如果删除节点仅有左孩子,直接指向左孩子
159+
} else if (root.left && !root.right) {
160+
root = root.left;
161+
// 3.如果删除节点仅有右孩子,直接指向右孩子
162+
} else if (!root.left && root.right) {
163+
root = root.right;
164+
} else {
165+
// 4.如果左右孩子都有,本代码采用方式是将后继的最小值替换root的值
166+
let last = root.right;
167+
while (last.left) {
168+
last = last.left;
169+
}
170+
root.val = last.val;
171+
// 然后删除这个后继最小值节点即可
172+
root.right = deleteNode(root.right, last.val);
173+
}
174+
}
175+
return root;
176+
};
177+
```
178+
179+
## 最后
180+
文章产出不易,还望各位小伙伴们支持一波!
181+
182+
往期精选:
183+
184+
<a href="https://github.com/Chocolate1999/Front-end-learning-to-organize-notes">小狮子前端の笔记仓库</a>
185+
186+
<a href="https://github.com/Chocolate1999/leetcode-javascript">leetcode-javascript:LeetCode 力扣的 JavaScript 解题仓库,前端刷题路线(思维导图)</a>
187+
188+
小伙伴们可以在Issues中提交自己的解题代码,🤝 欢迎Contributing,可打卡刷题,Give a ⭐️ if this project helped you!
189+
190+
191+
<a href="https://yangchaoyi.vip/">访问超逸の博客</a>,方便小伙伴阅读玩耍~
192+
193+
![](https://img-blog.csdnimg.cn/2020090211491121.png#pic_center)
194+
195+
```javascript
196+
学如逆水行舟,不进则退
197+
```
198+
199+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /