LeetCode Peoject 450.Delete Node in a BST

LeetCode Project

450.Delete Node in a BST

  • Difficulty : Medium
  • Description :

    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   7
    
    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 following BST.
    
        5
       / \
      4   6
     /     \
    2       7
    
    Another valid answer is [5,2,6,null,4,null,7].
    
        5
       / \
      2   6
       \   \
        4   7
    

题意为给出一棵搜索二叉树,并给出一个要删除的数字,在二叉树中寻找到该数字的节点,并将它删除,删除后要确保该二叉树仍未一棵搜索二叉树。

搜索二叉树是一种特殊的二叉树,在建立该树时将遵循这样一个规则:每个节点的左子树的值必定小于它的值,它的右子树的值必定大于它的值。

因此,当给定一定的数的时候,若建树时的顺序不一样,最后得到的树也将不一样,但是无论如何,它都符合搜索二叉树的定义。

此树在进行搜索时,近似于进行折半查找,故其平均时间复杂度为O(logn),但存在极端的情况,若给定的序列是有序的,此时该树将一直倾向于一边,此时退化为顺序查找,时间复杂度为O(n)。对于这种情况,我们可以将该二叉搜索树平衡化处理——即建造AVL树,此处不过多展开。

下图给出两种方法处理该题:

1.利用循环解决:

    public static TreeNode deleteNode(TreeNode root,int key){

        boolean solve = false;
        TreeNode temp = root;
        TreeNode parent = null;
        while (temp != null && !solve){
            if (temp.val == key){
                solve = true;
            }else if (key > temp.val){
                parent = temp;
                temp = temp.right;
            }else if (key < temp.val){
                parent = temp;
                temp = temp.left;
            }
        }

        if (!solve)
            return root;

        if (temp.left == null && temp.right == null){
            if (temp == root)
                return null;
            else if (parent.left == temp)
                parent.left = null;
            else
                parent.right = null;
        }else if (temp.left == null || temp.right == null){
            if (temp == root)
                if (temp.left == null)
                    return temp.right;
                else
                    return temp.left;
            else
                if (parent.left == temp && temp.left != null){
                    parent.left = temp.left;
                }else if (parent.left == temp){
                    parent.left = temp.right;
                }else if (parent.right == temp && temp.left != null){
                    parent.right = temp.left;
                }else {
                    parent.right = temp.right;
                }
        }else{
            TreeNode t = temp;
            TreeNode tc = temp.right;
            while (tc.left != null){
                t = tc;
                tc = tc.left;
            }
            temp.val = tc.val;
            if (t == temp)
                t.right = tc.right;
            else
                t.left = tc.right;

        }

        return root;
    }

具体思想就是先找出要删除的点与其父节点,然后将该节点的右子树的最左节点(最小)复制到被删除节点,然后直接删除最左节点,若该节点存在右子树,则将其右子树链接至其父节点的左子树上。

给出一个测试用例的图:
这里写图片描述

解得:

这里写图片描述

关注1图中33节点与34节点。

解法二:

利用递归删除,这种写法的好处是十分简短,时间复杂度较类似,但是本人比较难将这种方法想出来(递归学得不好)。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode deleteNode(TreeNode root,int key){
        if (root == null){
            return root;
        }

        if (root.val < key){
            root.right = deleteNode(root.right,key);
        }else if (root.val >key){
            root.left = deleteNode(root.left,key);
        }else if (root.left != null && root.right != null){
            root.val = findMin(root.right).val;
            root.right = deleteNode(root.right,root.val);
        }else{
            root = (root.left != null) ? root.left : root.right;
        }

        return root;
    }

    public TreeNode findMin(TreeNode root){
        while (root.left != null){
            root = root.left;
        }
        return root;
    }
}

解:

这里写图片描述

注意到35节点处发生了形状的改变,这是由于进行了递归删除,清除了33节点后,再清除34节点,故形成了该形状。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值