【LeetCode】450、删除二叉搜索树中的节点

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

题目描述:

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

  说明: 要求算法时间复杂度为 O(h),h 为树的高度。

示例:

root = [5,3,6,2,4,null,7]
key = 3
    5
   / \
  3   6
 / \   \
2   4   7
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
    5
   / \
  4   6
 /     \
2       7
另一个正确答案是 [5,2,6,null,4,null,7]。
    5
   / \
  2   6
   \   \
    4   7

解题思路:

  二叉搜索树有一个很好的性质:左小右大,并且对BST进行中序遍历(左、根、右)得到的序列正好是一个递增序列。本题就是基于BST的性质进行结点的删除。

  前驱结点:Predecessor 代表的是中序遍历序列的前一个节点。即比当前节点小的最大节点,简称前驱节点。先取当前节点的左节点,然后取该节点的右节点,直到右节点为空,则最后指向的节点为前驱节点。

public int predecessor(TreeNode root) {
  root = root.left;
  while (root.right != null) 
      root = root.right;
  return root;
} 

  后继结点:Successor 代表的是中序遍历序列的下一个节点。即比当前节点大的最小节点,简称后继节点。 先取当前节点的右节点,然后一直取该节点的左节点,直到左节点为空,则最后指向的节点为后继节点。

public int successor(TreeNode root) {
  root = root.right;
  while (root.left != null) 
      root = root.left;
  return root;
} 

删除算法:

  • 如果 key > root.val,说明要删除的节点在右子树,root.right = deleteNode(root.right, key)。
  • 如果 key < root.val,说明要删除的节点在左子树,root.left = deleteNode(root.left, key)。
  • 如果 key == root.val,则该节点就是我们要删除的节点,则:

  (1)如果该节点是叶子节点,则直接删除它:root = null。

  (2)如果该节点只有左子树或者只有右子树,则跳过根,直接返回左子树或右子树。

  (3)如果该节点左右子树都存在,则用它的后继节点的值替代 root.val = successor.val,然后删除后继节点。

代码实现:

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
    	//BST,左小右大
        if(root==null)
        	return null;
        
        if(key<root.val)   //左子树递归
            root.left=deleteNode(root.left,key);
        else if(key>root.val)  //右子树递归
            root.right=deleteNode(root.right,key);
        else{  //相等,则要删除的就是root
            if(root.left==null && root.right==null)  //左右都空,叶结点
            	root=null;
            else if(root.right==null)  //右为空,返回左
                root=root.left;
            else if(root.left==null)  //左为空,返回右
                root=root.right;
            else{  //左右都不空,找后继结点代替,右子树最左边
                TreeNode parent=root.right;
                if(parent.left==null){
                    root.val=parent.val;
                    root.right=parent.right;
                }else{
                    TreeNode temp=parent.left;
                    while(temp.left!=null){
                        parent=temp;
                        temp=temp.left;
                    }
                    root.val=temp.val;
                    parent.left=temp.right;
                }
            }
        }
        return root;
    }
}
posted @ 2020-04-01 22:20  gzshan  阅读(412)  评论(0编辑  收藏  举报