细数算法知识点—删除二叉搜索树中的节点

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

1. 思路分析

这个题是比较复杂的,原因是删除节点后,最终的二叉树依旧是一棵二叉搜索树。
难点:

  1. 如何定位到要删除的节点?
  2. 删除节点后,二叉树如何移动使其依旧是一棵二叉搜索树?

二叉搜索树性质:

  1. 中序搜索默认是升序集合;
  2. 所有左子树节点都比root节点小,所有右子树节点都比root节点大

思路:

1. 方法的返回值:是删除节点后返回的新的root节点。

知识点:利用二叉搜索树的性质,可以只搜索半条边就定位到待删除节点的位置,注意需要重新建立指针关系。

2. 删除节点后,新root节点为左子树的最大节点或者右子树最小节点。

知识点:转换为获取二叉树右子树最小节点的题型,将右子树最小节点的值赋值给待删除的节点,然后删除右子树最小节点。

3. 如何找到右子树最小节点?

二叉搜索树中序遍历是有序的,即最左子树为最小节点。

private TreeNode min(TreeNode root){
  if(root.left==null){
    return root;
  }
  return min(root.left);
}

2. 结题算法

2.1 寻找右子树最小节点

节点一直向左子树遍历,左子树遇到空时,表示遍历到了末尾。即最小节点。

private TreeNode min(TreeNode root){
  if(root.left==null){
    return root;
  }
  return min(root.left);
}

2.2 删除右子树最小节点

删除右子树最小节点后,并返回root节点

由此操作得到的二叉树依旧是二叉搜索树。

  1. 二叉搜索树性质:所有左子树小于root节点,所有右子树大于root节点。

(1)最小节点的左子树为空,即没有比它更小的节点;
(2)最小节点右子树节点依旧小于最小节点的root节点;
(3)删除最小节点后,将最小节点的right节点挂在最小节点父结点的left指针上。

注意:递归方法返回的是最小结点的right结点。然后最小结点的父结点left指针由最小结点指向最小结点的右孩子。完成最小结点的删除。

    //删除最小节点后,返回root节点
    private TreeNode delMin(TreeNode root){
        if(root.left==null){
            return root.right;
        }
        root.left=delMin(root.left);
        return root;
    }

2.3 二分搜索值

  1. 若key大于root节点的值,那么待删除的节点在右子树;
    1.1 递归方法返回的是删除后的节点,使用root重建树;
  2. 若key小于root节点的值,那么待删除的节点在左子树。
    2.1 递归方法返回的是删除后的节点,使用root重建树;
  3. 若key等于root节点的值:
    3.1 若root是叶子节点,直接删除;
    3.2 若root是单子树节点,那么返回子树的后续节点(即把root节点删除后输出)
    3.3 若root存在左右子树:
    -3.3.1 找到右子树的最小节点;
    -3.3.2 删除右子树最小节点,并返回root节点;
    -3.3.3 使用右子树最小节点的值替换待删除节点的值;

3. 最终结果

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root==null){
            return null;
        }
        //左子树寻找节点
        if(keyroot.val){
           //右子树得到删除后的节点
           TreeNode newRight= deleteNode(root.right,key);
           root.right=newRight;
           return root; 
        }else{
            //找到节点后,替换节点,删除右子树最小节点
            //1. 若是叶子节点,直接删除
            if(root.left==null&&root.right==null){
                return null;
            }
            //2. 若是左子树节点
            else if(root.left!=null&&root.right==null){
                return root.left;
            }
            else if(root.right!=null&&root.left==null){
                return root.right;
            }
            //两个节点同时存在时
            else{
              //寻找右子树最小节点
              TreeNode node =  min(root.right);
              //删除右子树最小节点,并返回根节点,root的右节点指向新的子树节点
              root.right = delMin(root.right);
              //替换节点
              root.val=node.val;
              return root;
            }
        }
    }

    //获取最小节点
    private TreeNode min(TreeNode root){
        if(root.left==null){
            return root;
        }
        return min(root.left);
    }

    //删除最小节点后,返回root节点
    private TreeNode delMin(TreeNode root){
        if(root.left==null){
            return root.right;
        }
        root.left=delMin(root.left);
        return root;
    }
}

你可能感兴趣的:(细数算法知识点—删除二叉搜索树中的节点)