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


    给定一个二叉搜索树的根节点 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

    思路:

      • 二叉搜索树,因为其是有序的,左边的节点都比根节点小,右边的节点都比根节点大;
      • 要删除某一个节点,分情况讨论:1. 如果是叶节点,则直接删除;
      • 2.如果是非叶子节点,且有左儿子节点,则找到其前驱节点(因为前驱节点是:在比当前节点小的节点中,最大的一个,将他放到当前节点位置,其左边的儿子节点还是都比他小,满足二叉搜索树定义);
      • 3.如果是非叶子节点,且没有左儿子,只有右儿子节点,则找到其后继节点(因为后继节点是:比当前节点大的节点中,最小的那一个,将他替换后,满足右边都比他大);
      • 将当前节点的值,换为前驱/后继节点的值,再递归删除这个前驱/后继节点即可。

    class Solution {
        public TreeNode deleteNode(TreeNode root, int key) {
            if(root == null) return null;
            if(key < root.val) root.left = deleteNode(root.left, key); //key在左边子节点
            else if(key > root.val) root.right = deleteNode(root.right, key); //key在右边子节点
            else{ // 当前节点就是需要删除的节点
                if(root.left == null && root.right == null) return null;//如果是叶子节点,直接删除即可
                else if(root.left != null){ //非叶子节点,如果有左儿子节点,则寻找其前驱节点
                    int num = preNode(root);
                    root.val = num; //将前驱节点的值,赋给当前节点,删掉这个前驱节点
                    root.left = deleteNode(root.left, num);
                }else{ // 非叶子节点,如果没有左儿子,但有右儿子节点,寻找其后继节点
                    int num = afterNode(root);
                    root.val = num; //同理,删掉后继节点
                    root.right = deleteNode(root.right, num);
                }
            }
            return root; //返回根节点
        }
        private int preNode(TreeNode root){ //寻找根节点的前驱节点
            root = root.left;
            while(root.right != null) root = root.right;
            return root.val;
        }
    
        private int afterNode(TreeNode root){ //寻找根节点的后继节点
            root = root.right;
            while(root.left != null) root = root.left;
            return root.val;
        }
    }
  • 相关阅读:
    Linux入门之系统启动
    2017.12.25 Android数据存储方案
    2017.12.18 Android开发之进程讲解
    2017.12.18 Android开发之消息队列(实现子线程修改UI组件)
    2017.12.4 Android开发之ListView组件
    2017.12.10 把KIE的jbpm_console嵌入到我们的web项目中
    2017.12.07 React组件嵌套以及for循环渲染子组件
    2017.12.07 React路由到不同组件界面
    2017.12.07 Ajax获取服务器数据并发送到前端
    B-树&B+树以及其在数据库中的应用
  • 原文地址:https://www.cnblogs.com/luo-c/p/13944400.html
Copyright © 2020-2023  润新知