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

在这里插入图片描述

思考问题的时候一定要跳出之前的思维圈,一旦出错,就会一直困在里面!!!!
删除二叉搜索树,在学数据结构的时候用C语言手敲了一遍。现在用Java来实现,发现毫无头绪!!!于是又在回忆之前的思路,结果越想越乱。
然后完全抛弃之前的想法,开始独立思考。随便指定实例中的一个节点的时候,就发现了三种情况,俺就是这个节点可能含有左右儿子中的一个,或者两个都有,或者根本就没有儿子节点。那么对于不同的情况就要有不同的应对方式。
对于树的形状的改变,有两种方法。
第一种方法是,直接将有儿子替换当前节点,然后将当前节点的左儿子放在右儿子的最小节点的左儿子上。
第二种是将右儿子中的最小节点替换掉要被删除的节点。

下面是第一种方法(自己想的)
第一步肯定是dfs查找到目标节点,找到之后便要开始分析这个节点的具体情况。

            if (root.left == null && root.right == null) {
                return null;
            }
            if (root.left == null || root.right == null) {
                return root.left == null ? root.right : root.left;
            }
            root.right = insert(root.right, root.left);
            root = root.right;

第三步中,为什么要设置这样一个插入方法?因为在写出方法之前,曾经直接遍历到right中的最小节点,然后将root.left放在这个节点的左儿子上,但是发现了一个问题,那就是返回的时候节点并没有发生改变。所以这里用了一个递归生成一个新的子树,并将这个新子树替换掉当前子树。下面是完整代码。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        TreeNode ans = dfs(root, key);
        return ans;
    }
    

    public TreeNode dfs(TreeNode root, int key) {
        if (root == null) {
            return null;
        }
        if (key < root.val) {
            root.left = dfs(root.left, key);
        }
        if (key > root.val) {
            root.right = dfs(root.right, key);
        }
        if (root.val == key) {
            if (root.left == null && root.right == null) {
                return null;
            }
            if (root.left == null || root.right == null) {
                return root.left == null ? root.right : root.left;
            }
            root.right = insert(root.right, root.left);
            root = root.right;
        }
        return root;
    }

    public TreeNode insert(TreeNode node, TreeNode left) {
        if (node == null) {
            node = left;
            return node;
        }
        node.left = insert(node.left, left);
        return node;
    }
}

下面是第二种方法,按照大佬思路写的。前段部分的思路和之前是样的,不同的只有在找到节点之后的做法。直接找到右子树中最小的值的,然后修改当前root的值,最后调用delete方法删除掉这个最小的值。

class Solution {
   public TreeNode deleteNode(TreeNode root, int key) {
        TreeNode ans = dfs(root, key);
        return ans;
    }


    public TreeNode dfs(TreeNode root, int key) {
        if (root == null) {
            return null;
        }
        if (key < root.val) {
            root.left = dfs(root.left, key);
        }
        if (key > root.val) {
            root.right = dfs(root.right, key);
        }
        if (root.val == key) {
            if (root.left == null && root.right == null) {
                return null;
            }
            if (root.left == null || root.right == null) {
                return root.left == null ? root.right : root.left;
            }
            /*root.right = insert(root.right, root.left);
            root = root.right;*/
            int val = findMin(root.right);
            root.val = val;
            root.right = deleteNode(root.right, val);
            
        }
        return root;
    }

    public int findMin(TreeNode node) {
        if (node.left == null) {
            return node.val;
        }
        return findMin(node.left);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值