博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LeetCode] Delete Node in a BST 删除二叉搜索树中的节点
阅读量:7079 次
发布时间:2019-06-28

本文共 3774 字,大约阅读时间需要 12 分钟。

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   7Given 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       7Another 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的右子节点连上删除后的节点。在删除函数中,如果左右子节点都不存在,那么返回空;如果有一个不存在,那么我们返回那个存在的;难点还是在于处理左右子节点都存在的情况,还是要找到需要删除节点的右子树中的最小值,然后把最小值赋值给要删除节点,然后就是要处理最小值可能存在的右子树的连接问题,如果要删除节点的右子节点没有左子节点了的话,那么最小值的右子树直接连到要删除节点的右子节点上即可(因为此时原本要删除的节点的值已经被最小值替换了,所以现在其实是要删掉最小值节点)。否则我们就把最小值节点的右子树连到其父节点的左子节点上。文字表述确实比较绕,请大家自行带例子一步一步观察就会很清晰明了了,参见代码如下:

解法二:

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

下面来看一种对于二叉树通用的解法,适用于所有二叉树,所以并没有利用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;    }};

本文转自博客园Grandyang的博客,原文链接:,如需转载请自行联系原博主。

你可能感兴趣的文章
动态重载与静态重载
查看>>
Activiti模板相关功能详解
查看>>
Android Design与Holo Theme详解
查看>>
Json的笔记和摘抄
查看>>
学习插入排序算法
查看>>
自动类型变量auto和静态变量static学习
查看>>
[Android] android的消息队列模型
查看>>
HTML5 Geolocation 整合百度地图显示当前位置
查看>>
字符型2
查看>>
Windows下安装JDK
查看>>
MySQL性能优化的21个最佳实践 和 mysql使用索引
查看>>
js循环的是数组不是对象
查看>>
tomcat 配成用 https方式访问
查看>>
log 日志输出级别的选择
查看>>
vector内存增长方式
查看>>
How to install webcamd--安装webcamd
查看>>
acl_cpp 的 rpc 相关类整合阻塞及非阻塞过程
查看>>
Android屏幕大小适配问题解决
查看>>
设计模式的设计原则
查看>>
java.lang.OutOfMemoryError: Java heap space解决办法
查看>>