Leetcode:450. 删除二叉搜索树中的节点

133 篇文章 0 订阅

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

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

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

说明: 要求算法时间复杂度为 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

解题思路:

递归。

  1. 利用递归查询数值为key的节点,如果没有,原封不动地返回原来地树。
  2. 找到待删除地点node,node地状态可能有下面几种。
  3. node没有孩子,那么直接删除这个节点,返回root,如果root,恰好被删除,那么返回null。
  4. node只有左孩子,将node->left替换node。
  5. node有两个孩子。找到右子树中最靠左(数值最小)的点去替代node,如果node->right恰好是最左的点,那么,将node的左子树直接嫁接到node->right->left。再将node->right替换node。
  6. 最终返回root,注意root可能是待删除的点。

C++代码
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        TreeNode* node = find(root, key);
        if (node == NULL) return root;
        if (!node->right) {
            if (!key_father) return node->left;
            if (key_father->left == node) key_father->left = node->left;
            else key_father->right = node->left;
            return root;
        }
        if (!node->right->left) {
            node->right->left = node->left;
            if (!key_father) return node->right;
            if (key_father->left == node) key_father->left = node->right;
            else key_father->right = node->right;
            return root;
        }
        //查找node右子树中最左的点。
        TreeNode *left, *left_father;
        left_father = node->right;
        left = left_father->left;
        while (left) {
            if (left->left) {
                left_father = left;
                left = left->left;
            }
            else break;
        }
        left_father->left = left->right;
        left->left = node->left;
        left->right = node->right;
        if (!key_father) {
            return left;
        }
        if (key_father->left == node) {
            key_father->left = left;
        }
        else {
            key_father->right = left;
        }
        node->left = NULL;
        node->right = NULL;
        delete node;
        return root;
    }
    TreeNode* find(TreeNode* root, int key) {
        if (!root) return NULL;
         if (root->val == key) return root;
        if ((root->left)&&root->left->val == key || (root->right)&&root->right->val == key) key_father = root;
        if (root->val > key) return find(root->left, key);
        if (root->val < key) return find(root->right, key);
    }
    TreeNode* key_father;
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值