Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.

Basically, the deletion can be divided into two stages:

  1. Search for a node to remove.
  2. If the node is found, delete the node.

Note: Time complexity should be O(height of tree).

Example:

root = [5,3,6,2,4,null,7]
key = 3 5
/ \
3 6
/ \ \
2 4 7 Given key to delete is 3. So we find the node with value 3 and delete it. One valid answer is [5,4,6,2,null,null,7], shown in the following BST. 5
/ \
4 6
/ \
2 7 Another valid answer is [5,2,6,null,4,null,7]. 5
/ \
2 6
\ \
4 7

这道题让我们删除二叉搜索树中的一个节点,难点在于删除完结点并补上那个结点的位置后还应该是一棵二叉搜索树。被删除掉的结点位置,不一定是由其的左右子结点补上,比如下面这棵树:

7
        / \
       4   8
     /   \   
    2     6
     \   /
      3 5

如果要删除结点4,那么应该将结点5补到4的位置,这样才能保证还是 BST,那么结果是如下这棵树:

7
        / \
       5   8
     /   \   
    2     6
     \   
      3

先来看一种递归的解法,首先判断根节点是否为空。由于 BST 的左<根<右的性质,使得可以快速定位到要删除的结点,对于当前结点值不等于 key 的情况,根据大小关系对其左右子结点分别调用递归函数。若当前结点就是要删除的结点,先判断若有一个子结点不存在,就将 root 指向另一个结点,如果左右子结点都不存在,那么 root 就赋值为空了,也正确。难点就在于处理左右子结点都存在的情况,需要在右子树找到最小值,即右子树中最左下方的结点,然后将该最小值赋值给 root,然后再在右子树中调用递归函数来删除这个值最小的结点,参见代码如下:

解法一:

class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (!root) return NULL;
if (root->val > key) {
root->left = deleteNode(root->left, key);
} else if (root->val < key) {
root->right = deleteNode(root->right, key);
} else {
if (!root->left || !root->right) {
root = (root->left) ? root->left : root->right;
} else {
TreeNode *cur = root->right;
while (cur->left) cur = cur->left;
root->val = cur->val;
root->right = deleteNode(root->right, cur->val);
}
}
return root;
}
};

下面来看迭代的写法,还是通过 BST 的性质来快速定位要删除的结点,如果没找到直接返回空。遍历的过程要记录上一个位置的结点 pre,如果 pre 不存在,说明要删除的是根结点,如果要删除的结点在 pre 的左子树中,那么 pre 的左子结点连上删除后的结点,反之 pre 的右子结点连上删除后的结点。在删除函数中,首先判空,若为空,直接返回空指针;否则检测若右子结点不存在,直接返回左子结点即可,因为没有右子树就不会牵扯到调整树结构的问题;若右子结点存在,需要找到右子树中的最小值,即右子树中的最左子结点,用一个 while 循环找到即可,然后将要删除结点的左子结点连到右子树的最左子结点的左子结点上即可(说的有点绕,大家仔细体会一下),最后返回要删除结点的右子结点即可,文字表述确实比较绕,请大家自行带例子一步一步观察就会很清晰明了,参见代码如下:

解法二:

class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (!root) return nullptr;
TreeNode *cur = root, *pre = nullptr;
while (cur) {
if (cur->val == key) break;
pre = cur;
if (cur->val > key) cur = cur->left;
else cur = cur->right;
}
if (!pre) return del(cur);
if (pre->left && pre->left->val == key) pre->left = del(cur);
else pre->right = del(cur);
return root;
}
TreeNode* del(TreeNode* node) {
if (!node) return nullptr;
if (!node->right) return node->left;
TreeNode *t = node->right;
while (t->left) t = t->left;
t->left = node->left;
return node->right;
}
};

下面来看一种对于二叉树通用的解法,适用于所有二叉树,所以并没有利用 BST 的性质,而是遍历了所有的结点,然后删掉和 key 值相同的结点,参见代码如下:

解法三:

class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (!root) return NULL;
if (root->val == key) {
if (!root->right) return root->left;
else {
TreeNode *cur = root->right;
while (cur->left) cur = cur->left;
swap(root->val, cur->val);
}
}
root->left = deleteNode(root->left, key);
root->right = deleteNode(root->right, key);
return root;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/450

类似题目:

Split BST

参考资料:

https://leetcode.com/problems/delete-node-in-a-bst/

https://leetcode.com/problems/delete-node-in-a-bst/discuss/93296/Recursive-Easy-to-Understand-Java-Solution

https://leetcode.com/problems/delete-node-in-a-bst/discuss/93378/An-easy-understanding-O(h)-time-O(1)-space-Java-solution.

https://leetcode.com/problems/delete-node-in-a-bst/discuss/93331/concise-c-iterative-solution-and-recursive-solution-with-explanations

https://leetcode.com/problems/delete-node-in-a-bst/discuss/93293/Very-Concise-C%2B%2B-Solution-for-General-Binary-Tree-not-only-BST

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 450. Delete Node in a BST 删除二叉搜索树中的节点的更多相关文章

  1. [LeetCode] Delete Node in a BST 删除二叉搜索树中的节点

    Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...

  2. 450 Delete Node in a BST 删除二叉搜索树中的结点

    详见:https://leetcode.com/problems/delete-node-in-a-bst/description/ C++: /** * Definition for a binar ...

  3. Java实现 LeetCode 450 删除二叉搜索树中的节点

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

  4. [Swift]LeetCode450. 删除二叉搜索树中的节点 | Delete Node in a BST

    Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...

  5. LeetCode 530. Minimum Absolute Difference in BST (二叉搜索树中最小绝对差)

    Given a binary search tree with non-negative values, find the minimum absolute difference between va ...

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

    思路: (1)如果root为空,返回 (2)如果当前结点root是待删除结点: a:root是叶子结点,直接删去即可 b:root左子树不为空,则找到左子树的最大值,即前驱结点,使用前驱结点代替待删除 ...

  7. [LeetCode] Inorder Successor in BST II 二叉搜索树中的中序后继节点之二

    Given a binary search tree and a node in it, find the in-order successor of that node in the BST. Th ...

  8. [CareerCup] 4.6 Find Next Node in a BST 寻找二叉搜索树中下一个节点

    4.6 Write an algorithm to find the'next'node (i.e., in-order successor) of a given node in a binary ...

  9. [leetcode]450. Delete Node in a BST二叉搜索树删除节点

    二叉树变量只是一个地址 public static void main(String[] args) { TreeNode t = new TreeNode(3); help(t); System.o ...

随机推荐

  1. 网易云信技术分享:IM中的万人群聊技术方案实践总结

    本文来自网易云信团队的技术分享,原创发表于网易云信公众号,原文链接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,收录时有改动. 1.引言 在不了解IM技术的人眼 ...

  2. mysql派生查询必须有别名问题记录

    最近在做mysql sql兼容,原来是oracle的sql都要保证在mysql数据库运行 业务场景:原来是一个带有子查询的sql,在oracle是可以正常运行的,迁到mysql就发现报错了,报错信息如 ...

  3. RoadMap:如何创建产品路线图

    (1)什么是Roadmap? RoadMap/产品路线图 Roadmap通常翻译为“路线图”或“蓝图”,目前并没有一个公认的定义.在这里,我们认为Roadmap是产品经理进行产品管理的一个中长期规划, ...

  4. POJ-2661Factstone Benchmark

    Factstone Benchmark Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5577   Accepted: 25 ...

  5. 机器学习(八)--------支持向量机 (Support Vector Machines)

    与逻辑回归和神经网络相比,支持向量机或者简称 SVM,更为强大. 人们有时将支持向量机看作是大间距分类器. 这是我的支持向量机模型代价函数 这样将得到一个更好的决策边界 理解支持向量机模型的做法,即努 ...

  6. Spring源码系列 — 容器Extend Point(一)

    前言 前文介绍了Spring中的BeanDefinition的细节,随着Spring的启动流程,这节我们介绍Spring的后续处理过程 - Spring的扩展点: BeanFactoryPostPro ...

  7. Spring集成Quartz框架的两种方式。

    可参考:https://blog.csdn.net/yk614294861/article/details/84324603 1.使用Spring与Quarta配置作业得两种方式: a.方式一,Met ...

  8. SocketServer模块与简单并发服务器

    思维导图文件:https://files-cdn.cnblogs.com/files/benjieming/SocketServer%E6%A8%A1%E5%9D%97%E4%B8%8E%E7%AE% ...

  9. JAVA8新特性--集合流操作Stream

    原文链接:https://blog.csdn.net/bluuusea/article/details/79967039 Stream类全路径为:java.util.stream.Stream 对St ...

  10. Mobx总结以及mobx和redux区别

    Mobx解决的问题 传统react使用的数据管理库为Redux.Redux要解决的问题是统一数据流,数据流完全可控并可追踪.要实现该目标,便需要进行相关的约束 Redux由此引出dispatch ac ...