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

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。

这道题完全可以利用二叉树的递归原理来解决,
只需要找到要删除的结点,然后判断

  1. 如果是叶子结点,可以直接删除
  2. 如果有左子树没有右子树,左子树就代替删除的结点位置
  3. 如果有右子树,就用右子树上最小的结点来代替删除的结点位置
  4. 要注意删除结点为跟结点的情况和树中只有一个结点的情况。

今天在刷题的时候又看到了这道题,这次没有用到递归,会显得代码比较复杂,但执行速度好像变快了,就想分享出来。
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //1.首先要删除的结点cur
        TreeNode pre = null;
        TreeNode cur = root;
        while (cur != null) {
            if (cur.val == key) {
                break;
            }
            pre = cur;
            if (cur.val > key) {
                cur = cur.left;
            } else {
                cur = cur.right;
            }
        }
        if (cur == null) {//说明没有找到,不需要删除任何元素
            return root;
        }
        if (cur.left == null && cur.right == null) {//说明删除的是叶子结点
            if (pre == null) {//只有跟结点一个
                return null;
            }
            if (pre.left == cur) {
                pre.left = null;
            } else {
                pre.right = null;
            }
            return root;
        }
        if (cur.right == null) {//只有左树
            if (pre == null) {//要删除的是跟结点
                return root.left;
            }
            if (pre.left == cur) {
                pre.left = cur.left;
            } else {
                pre.right = cur.left;
            }
            return root;
        }
        //2.找到cur的右树上的最小(左)的结点替换cur的位置
        if (cur.right == null) {//如果右树等于空
            if (pre == null) {
                return root.left;
            }
            pre.left = cur.left;
            return root;
        }
        TreeNode rightCur = getRightMinNode(cur);//得到并删除了右子树中最小的结点
        rightCur.left = cur.left;
        rightCur.right = cur.right;
        if (pre == null) {//如果cur是跟结点
            return rightCur;
        }
        if (pre.left == cur) {
            pre.left = rightCur;
        } else {
            pre.right = rightCur;
        }
        return root;

    }
    //找到cur的右树中最小的结点并删除
    public TreeNode getRightMinNode(TreeNode cur) {
        TreeNode rightCur = cur.right;//右树上最小的结点
        TreeNode rightPre = cur;//右树上最小的结点的父结点
        if (rightCur.left == null) {
            rightPre.right = rightCur.right;
            return rightCur;
        }
        //之后的情况就是rightCur只可能是rightPre的左孩子
        while (rightCur.left != null) {
            rightPre = rightCur;
            rightCur = rightCur.left;
        }
        rightPre.left = rightCur.right;
        return rightCur;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值