问题描述

给定一棵具有不同节点值的二叉查找树,删除树中与给定值相同的节点。如果树中没有相同值的节点,就不做任何处理。你应该保证处理之后的树仍是二叉查找树。


样例

给出如下二叉查找树:

5

      /    \

    3          6

 /    \

2       4

删除节点3之后,你可以返回:

5

   /    \

2          6

  \

     4

或者:

5

       /    \

    4          6

 /   

2

递归解法

首先判断根节点是否为空。根据二叉查找树的性质,我们可以快速定位到要删除的节点,我们对于当前节点值不等于key的情况,根据大小关系对其左右子节点分别调用递归函数。

若当前节点就是要删除的节点,我们首先判断是否有一个子节点不存在。如果它有一个子节点不存在,那么我们就让其父节点指向另一个节点。难点就在于处理左右子节点都存在的情况,我们需要在右子树找到最小值,即右子树中最左下方的节点,然后将该最小值赋值给当前节点,然后再在右子树中调用递归函数来删除这个值最小的节点。

class Solution {
public:
    /**
     * @param root: The root of the binary search tree.
     * @param value: Remove the node with given value.
     * @return: The root of the binary search tree after removal.
     */
     TreeNode* del(TreeNode* cur) {
        if(root==NULL) return NULL;
        if(root->val > value) {
            root->left = removeNode(root->left, value);
        } else if (root->val < value) {
            root->right = removeNode(root->right, value);
        } else {
            if (root->left==NULL || root->right == NULL) {
                return root->left==NULL ? root->right : root->left;
            } else {
                TreeNode* cur = root->right;
                while(cur->left!=NULL) cur= cur->left;
                root->val = cur->val;
                root->right = removeNode(root->right, cur->val);
            }
        }
        return root;
    }
};

非递归解法

通过二叉查找树,快速定位要删除的节点,如果没找到直接返回空。遍历的过程要记录上一个位置的节点pre。

如果pre不存在,说明要删除的是根节点;如果要删除的节点在pre的左子树中,那么pre的左子节点连上删除后的节点,反之pre的右子节点连上删除后的节点。

在删除函数中,如果左右子节点都不存在,那么返回空;如果有一个不存在,那么我们返回那个存在的;

难点还是在于处理左右子节点都存在的情况,还是要找到需要删除节点的右子树中的最小值,然后把最小值赋值给要删除节点,然后就是要处理最小值可能存在的右子树的连接问题。

如果要删除节点的右子节点没有左子节点了的话,那么最小值的右子树直接连到要删除节点的右子节点上即可(因为此时原本要删除的节点的值已经被最小值替换了,所以现在其实是要删掉最小值节点)。

否则我们就把最小值节点的右子树连到其父节点的左子节点上。

class Solution {
public:
    /**
     * @param root: The root of the binary search tree.
     * @param value: Remove the node with given value.
     * @return: The root of the binary search tree after removal.
     */
     TreeNode* del(TreeNode* cur) {
         if(cur->left == NULL || cur->right == NULL){
             return cur->left == NULL ? cur->right : cur->left;
         }
         TreeNode* pre = cur, *node = cur->right;
         while (node->left) {
             pre = node;
             node = node->left;
         }
         cur->val = node->val;
         if (pre == cur)
            cur->right = node->right;
         else 
            pre->left = node->right;

         return cur;
     }

    TreeNode* removeNode(TreeNode* root, int value) {
        // write your code here
        TreeNode* pre = NULL, *cur = root;
        while(cur) {
            if (cur->val == value)
                break;
            pre = cur;
            if (cur->val > value){
                cur = cur->left;
            } else {
                cur = cur->right;
            }
        }

        if(cur==NULL) return root;

        if(pre==NULL) return del(cur);

        if(pre->left && pre->left->val == value) {
            pre->left = del(cur);
        } else {
            pre->right = del(cur);
        }

        return root;
    }
};