zoukankan      html  css  js  c++  java
  • 【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;
        }
    }
    
  • 相关阅读:
    shi_tomasi特征点,GFTTDetector
    特征点总结(按features2d.hpp源码由上至下总结)
    经过一年时间的沉淀 再次回首 TCP Socket服务器编程 (二)
    构建嵌入式小型Linux系统
    老赵书托(3):深入理解计算机系统
    #define与typedef区别
    Linux下快速静态编译Qt以及Qt动态/静态版本共存
    tcpdump示例
    linux绑定多个ip(转载)
    Linux下eclipse及mysql安装,c++访问mysql数据库
  • 原文地址:https://www.cnblogs.com/gzshan/p/12616412.html
Copyright © 2011-2022 走看看