Loading

【leetcode】 450. 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. 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.

Example 1:Input: root = [5,3,6,2,4,null,7],

key = 3Output: [5,4,6,2,null,null,7]

Explanation: 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 above BST. Please notice that another valid answer is [5,2,6,null,4,null,7] and it's also accepted.

  首先对于BST 来说左子树的节点都比根节点小,右子树的节点都比根节点大,由此可以递归寻找到需要删除的节点。

       在删除当前节点的时候需要在该节点的子树中寻找替换节点,同时还要保证BST特性,有点像堆的插入和删除,为了保证依旧保持BST特性,那么替换的节点就是左子树的最大值,或者右子树的最小值,按照这个思路可以把代码写出来。

      1、复杂版本 想看最优化的代码请看2号答案,但是下面这个答案确确实实是我第一时间想到的写法,deleteNode 用于检索需要删除的节点find_right find_left 分别用于寻找左子树的最大值,或者右子树的最小值,由于需要替换节点所以还保存了前后两个节点用于删除子树,这个写法很麻烦。而且代码没有完全oc,oc了95%,不知道问题在哪儿。


/**
 * 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 {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        //递归 检索由于是bst 二叉树 根据其特性可以快速查找对应的节点
         if(root==nullptr) return nullptr;
         
         if(root->val<key){
             root->right=deleteNode(root->right,key);
         }
         else if(root->val>key){
             root->left=deleteNode(root->left,key);
         }
         else if(root->val==key){
             // 替换当前节点 需要寻找右子树的最小节点 或者左子树的最大节点
             // 如果右子树为空 就得去找左子树 如果左子树为空就得找右子树
             TreeNode* node=nullptr;
             if(root->right!=nullptr){
                  node= find_right(root,root->right); //寻找右子树的最小节点
                  node->left=root->left;
                  node->right=root->right;
                  
             }
             else if(root->left!=nullptr){
                  node= find_left(root,root->left); //寻找左子树的最大节点
                  node->left=root->left;
                  node->right=root->right;
             }
             return node; 
         }
         return root; 
    }
    
     TreeNode* find_right(TreeNode* node,TreeNode* node1){
         //存储最后两个节点
         TreeNode* root=node;
         while(node1->left!=nullptr){
             node=node1;
             node1=node1->left;
         }
         if(node==root){
             node->right=node1->right;
         }
         else{
             node->left=node1->left;
         }
         return node1;
         
     }
    
    TreeNode* find_left(TreeNode* node,TreeNode* node1){
         //存储最后两个节点
         TreeNode* root=node;
         while(node1->right!=nullptr){
             node=node1;
             node1=node1->right; //寻找左子树最大的数
         }
         if(node==root){
             node->left=node1->left;
         }
         else{
             node->right=node1->right;
         }
         return node1;
     }
};

  2、优化版本,在替换节点的时候可以分三种情况判断以下,(1)无左右子树、(2)只有左子树或者右子树(只要的话删除当前节点即可)、(3)同时有左子树或者右子树,替换后再调用一次deleteNode 即可

/**
 * 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 {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        //递归 检索由于是bst 二叉树 根据其特性可以快速查找对应的节点
         if(root==nullptr) return nullptr;
         
         if(root->val<key){
             root->right=deleteNode(root->right,key);
         }
         else if(root->val>key){
             root->left=deleteNode(root->left,key);
         }
         else if(root->val==key){
             // 替换当前节点 需要寻找右子树的最小节点 或者左子树的最大节点
             // 分三种情况讨论论 
             // 1 当前节点没有左右子树
             if(!root->left && !root->right) return nullptr;
             // 2 当前节点只有左子树 或者右子树
             else if(!root->left || !root->right)
                 return root->left ? root->left:root->right;
             // 3 当前节点同时有 左子树和右子树 则用左子树的最大节点替换当前节点
             TreeNode* node=root->left;
             while(node->right!=nullptr) node=node->right;
             // 替换当前节点
             root->val=node->val;
             //但是还要 删除掉这个最右边的节点 下边这个复杂的答案是同时存储两个节点 手动删除
             //但是 仔细思考一下 删除这个最右边的节点不就是再调用一遍deleteNode 函数嘛?
             root->left=deleteNode(root->left,node->val);
 
         }
         return root; 
    }
    
};

 

posted @ 2021-11-22 20:49  aalanwyr  阅读(45)  评论(0编辑  收藏  举报