leetcode——第450题——删除二叉搜索树的节点

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

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

首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
// /********************* 法一:BST 递归法*******************************/
// public:
//     TreeNode* deleteNode(TreeNode* root, int key) 
//     {
//         // 终止条件,也是第1种情况,如果遇到了空节点,说明没找到,那就直接返回咯
//         if(root ==nullptr)
//         {
//             return root;
//         }
//         // 当找到对应节点时,又分了4种情况
//         if(root->val == key)
//         {
//             // 第二种情况,左右孩子都为空,直接删除节点,返回 nullptr为根节点
//             // 第三种情况,左孩子为空,右孩子不为空,直接删除节点,右孩子补位
//             // 第四种情况,右孩子为空,左孩子不为空,直接删除节点,左孩子补位
//             // 注意::第二种情况可以和第三或者第四合并一下
//             if(root->left == nullptr)   // 合并了第二种情况
//             {
//                 return root->right;
//             }
//             else if(root->right == nullptr)
//             {
//                 return root->left;
//             }
//             // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到
//             // 删除节点的右子树的最左面节点的左孩子的位置,并返回删除节点右孩子为新的根节点
//             else
//             {
//                 TreeNode* cur = root->right;    // 定义一个指针指向右子树,找右子树最左面的节点
//                 while(cur->left != nullptr)
//                 {
//                     // 找到右子树最左面的节点
//                     cur = cur->left;
//                 }
//                 cur->left = root->left; // 把要删除的节点的左子树放在上面找到的 cur 的左孩子的位置
//                 TreeNode* temp = root;  // 把root节点临时操作一下,
//                 root = root->right;     // 用root->right 覆盖root
//                 delete temp;            // 释放删除的节点的内存
//                 return root;            
//             }
//         }
//         if(root->val > key)
//         {
//             root->left = deleteNode(root->left, key);
//         }
//         if(root->val < key)
//         {
//             root->right = deleteNode(root->right, key);
//         }
//         return root;
//     }

// /************************法二:普通二叉树的 递归法****************************/
// // 普通二叉树的删除方式(没有使用搜索树的特性,遍历整棵树),用交换值的操作来删除目标节点。
// // 但是这种写法我不太能理解,也不是不太能,就是不能吧~  覆盖?????emmmmmm饿了
// public:
//     TreeNode* deleteNode(TreeNode* root, int key) 
//     {
//         if(root == nullptr)
//         {
//             return root;
//         }
//         if(root->val == key)
//         {
//             // 这里第二次操作目标值: 最终删除的作用
//             if(root->right == nullptr)
//             {
//                 return root->left;
//             }
//             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;
//    }

/***********************法三:迭代法*************************/
// 注意:BST 的迭代法都不用栈或者队列哦
// 模拟递归法中的逻辑来删除节点,但需要一个pre记录cur的父节点,方便做删除操作。
private:
    // 将目标节点(也就是要删除的节点)的左子树放到 目标节点的右子树的最左面节点的左孩子的位置上
    // 并返回目标节点右孩子为新的根节点
    TreeNode* deleteOneNode(TreeNode* target)
    {
        // 需要被删除节点为 空节点
        if(target == nullptr)
        {
            return target;
        }
        // 需要被删除节点的右子树为空节点
        if(target->right == nullptr)
        {
            return target->left;
        }
        TreeNode* cur = target->right;
        while(cur->left)
        {
            cur = cur->left;
        }
        cur->left = target->left;
        return target->right;
    }
public:
    TreeNode* deleteNode(TreeNode* root, int key) 
    {
        if(root == nullptr)
        {
            return root;
        }
        TreeNode* cur = root;
        TreeNode* pre = nullptr;    // 记录cur的父节点,用来删除 cur
        // 通过while循环找到要删除的节点 cur
        while(cur)
        {
            if(cur->val == key)
            {
                break;
            }
            pre = cur;
            if(cur->val > key)
            {
                cur = cur->left;
            }
            else
            {
                cur = cur->right;
            }
        }
        // pre == nullptr 说明根本没进 while 循环,即该树只有头结点
        if(pre == nullptr)
        {
            return deleteOneNode(cur);
        }
        if(pre->left != nullptr && pre->left->val == key)
        {
            pre->left = deleteOneNode(cur);
        }
        if(pre->right != nullptr && pre->right->val == key)
        {
            pre->right =deleteOneNode(cur);
        }
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值