19. 二叉搜索树的插入删除修剪

title: 二叉搜索树的插入删除修剪

📃 题目一描述

题目链接:701. 二叉搜索树中的插入操作

19. 二叉搜索树的插入删除修剪

19. 二叉搜索树的插入删除修剪

🔔 解题思路

递归法:

明确BST插入可以不用改变树的结构,所以找到对应的子节点插入即可;

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == nullptr) {
            return new TreeNode(val);
        }

        if (val > root->val) root->right = insertIntoBST(root->right, val);
        if (val < root->val) root->left = insertIntoBST(root->left, val);
        return root;
    }
};

迭代法:

找到叶子节点,但是是迭代的,无法像递归一样利用函数调用的栈,但是可以采用pre 来记录上一个的节点!

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        TreeNode* cur = root;
        TreeNode* pre = nullptr;
        while (cur) {
            pre = cur;
            if (cur->val > val) {
                cur = cur->left;
            }
            else if (cur->val < val) {
                cur = cur->right;
            }
        }
        if (pre && pre->val > val) pre->left = new TreeNode(val);
        else if (pre && pre->val < val) pre->right = new TreeNode(val);
        else root = new TreeNode(val);
        return root;
    }
};

💥 复杂度分析

  • 时间复杂度:O(n);
  • 空间复杂度:O(1);

📃 题目二描述

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

19. 二叉搜索树的插入删除修剪

19. 二叉搜索树的插入删除修剪

🔔 解题思路

找到删除节点要观察:

情况一:要删除的节点是叶子节点,直接删除即可;

情况二:要删除的节点是只存有一边子树,直接删除用子树的第一个节点替上来就可;

情况三:要删除的节点存在左右两边子树,那么删除可以有多种选择方案,这里提两种

  • 方案①:用删除节点的右子树第一个节点替代,如图:19. 二叉搜索树的插入删除修剪
  • 方案②用删除节点的右子树最小值来替代,如上图,用4代替7;
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return nullptr; // 处理找不到的情况;
        if (root->val == key) {
            // 处理情况一、二
            if (root->left == nullptr) {
                TreeNode* cur = root->right;
                delete root;
                return cur;
            }
            if (root->right == nullptr) {
                TreeNode* cur = root->left;
                delete root;
                return cur;
            }
            // 情况三
            if (root->left && root->right) {
                TreeNode* node = root->right;
                while (node->left) node = node->left; // 拿到右子树最小的值;
                // 方案①:将右子节点替上去;
                node->left = root->left;
                TreeNode* cur = root->right;
                delete root;
                return cur;
                //方案②:将右子树中的最小值替上去;
                node = new TreeNode(node->val);
                root->right = deleteNode(root->right, node->val);
                node->left = root->left; node->right = root->right;
                delete root;
                return node;
            }
        }
        // 找左右子树
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }

};

迭代法:

class Solution {
public:
    TreeNode* deleteoOne(TreeNode* root) {
        // 情况一、二
        if (root->right == nullptr) return root->left;
        if (root->left == nullptr) return root->right;
        // 情况三,采用方案①
        TreeNode* cur = root->right;
        while (cur->left) cur = cur->left;
        cur->left = root->left;
        return root->right;
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return nullptr;
        TreeNode* pre = nullptr;
        TreeNode* cur = root;
        while (cur) {
            if (cur->val == key) break;
            pre = cur;
            if (cur->val > key) cur = cur->left;
            else cur =cur->right;
        }
        // 如果要删除的是头节点
        if (pre == nullptr) return deleteoOne(cur);
        // 如果要删除的是pre左孩子节点
        if (pre->left && pre->left == cur) pre->left = deleteoOne(cur);
        // 如果要删除的是pre右孩子节点
        if (pre->right && pre->right == cur) pre->right = deleteoOne(cur);
        return root;
    }
};

💥 复杂度分析

  • 时间复杂度:O(n);
  • 空间复杂度:O(1);

📃 题目三描述

题目链接:669. 修剪二叉搜索树

19. 二叉搜索树的插入删除修剪

19. 二叉搜索树的插入删除修剪

🔔 解题思路

解法一:递归

利用BST树的性质,要明确当下节点可能 不再[low, high]区间内,但是其左子树或者右子树是存在这样的节点的;

自底而上不断改变树的结构,剔除不再[low,high]的节点,有:

  • 当前节点val < low ,那么它的右子树一定是在[low, high]区间内;
  • 相同的,val >high, 那么它的左子树一定在[low, high]区间内
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr) return nullptr;
        // 自底向上改变
        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);
        if (root->val > high) return root->left;
        else if (root->val < low) return root->right;
        else return root;
    }
};

解法二:迭代

看代码注释即可,思考应该返回什么?怎么修剪左右子树?

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        // 找到第一个符合[low, high] 的节点(当返回值);
        while (root && (root->val < low || root->val > high)) {
            if (root->val < low) root = root->right; // 当前值 < low
            else root = root->left; // 当前值 > low
        }
        // 修剪左子树
        TreeNode* cur =root;
        while (cur != nullptr) {
            while (cur->left && cur->left->val < low) { //找到符合[low, high]的节点 接入left
                cur->left = cur->left->right;
            }
            cur = cur->left;
        }
        // 修剪右子树
        cur = root;
        while (cur != nullptr) {
            while (cur->right && cur->right->val > high) { //找到符合[low, high]的节点 接入right
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }

        return root;
    }
};

💥 复杂度分析

  • 时间复杂度:O(n);
  • 空间复杂度:O(1);

Original: https://www.cnblogs.com/D-booker/p/16365889.html
Author: D-booker
Title: 19. 二叉搜索树的插入删除修剪

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713327/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • UTC时间、GMT时间、本地时间、Unix时间戳

    引用: https://blog.csdn.net/u012102306/article/details/51538574 https://blog.csdn.net/foxir/…

    技术杂谈 2023年5月31日
    098
  • 负载均衡之keepalived

    备份和修改keepalived配置文件 DR配置文件: cp keepalive.conf keepalived.conf.bak cat /etc/keepalived.conf…

    技术杂谈 2023年7月11日
    073
  • 小蜜蜂引起的jQuery插件

    Original: https://www.cnblogs.com/chenyjccxy/p/5032662.htmlAuthor: chenyjTitle: 小蜜蜂引起的jQue…

    技术杂谈 2023年7月23日
    061
  • 手撕堆排序(含图解,代码,复杂度分析,使用场景)

    本篇重点 什么是堆,有什么特性? 堆排序概述 堆排序图解 代码 堆排序时间复杂度/空间复杂度/稳定性 堆排序/堆适用场景 什么是堆 堆是完全二叉树。一棵深度为k的有n个结点的二叉树…

    技术杂谈 2023年6月21日
    090
  • 附加进程到远程服务器中Docker容器内调试

    很多时候,我们在本地开发过程中程序运行很正常,但是发布到线上之后由于环境的原因,可能会有一些异常。通常我们会通过日志来分析问题,除了日志还有一种常用的调试手段就是:附加进程。 VS…

    技术杂谈 2023年7月23日
    097
  • InnoDB什么时候会锁表?

    我们常常说InnoDB是行锁,但是这里介绍一下它锁表的情况。 InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来…

    技术杂谈 2023年5月31日
    0103
  • crash命令 —— irq

    参考:https://crash-utility.github.io/help_pages/irq.html 用法: 查看系统所有中断的使用信息,如虚拟中断号,中断的irq_des…

    技术杂谈 2023年5月30日
    096
  • 使用微软分布式缓存服务Velocity Part 2

    概述 Velocity是微软推出的分布式缓存解决方案,为开发可扩展性,可用的,高性能的应用程提供支持,可以缓存各种类型的数据,如CLR对象、XML、二进制数据等,并且支持集群模式的…

    技术杂谈 2023年5月31日
    0103
  • SpringBoot-shiro

    SpringBoot-shiro 12.1 快速入门 1、导入依赖 org.apache.shiro shiro-core 1.8.0 org.slf4j jcl-over-slf…

    技术杂谈 2023年6月21日
    096
  • Zookeeper全解析——Client端(转)

    Zookeeper的Client直接与用户打交道,是我们使用Zookeeper的interface。了解ZK Client的结构和工作原理有利于我们合理的使用ZK,并能在使用中更早…

    技术杂谈 2023年5月31日
    098
  • 最小二乘法小结

    http://www.cnblogs.com/pinard/p/5976811.html 最小二乘法是用来做函数拟合或者求函数极值的方法。在机器学习,尤其是回归模型中,经常可以看到…

    技术杂谈 2023年5月31日
    078
  • 归并排序

    跳转地址 归并排序的重点是合并,利用双指针算法,排序的是否稳定是指如果两个数的大小相同,在经过排序后相对位置不变,那么这个排序就是稳定的,否则就是不稳定的 归并排序的思路是将数组按…

    技术杂谈 2023年6月21日
    0100
  • Vue(十一)—key特殊attribute

    预期: number | string | boolean (2.4.2 &#x65B0;&#x589E;) | symbol (2.5.12 &#x65B…

    技术杂谈 2023年7月25日
    074
  • list,map,set的区别

    list,map,set的区别 (首先假定小猪都是同一个细胞克隆出来的) List = 排成一长队的小猪 Map = 放在一个个,有房间号的屋子里面的一群小猪 Set = 一群小猪…

    技术杂谈 2023年5月31日
    071
  • JAVA8-Lambda-groupingBy

    使用场景: 例:有一群来自五湖四海的大学生,这些学生按照他们的家乡组建一场同乡会。 public static void main(String[] args) { ArrayLi…

    技术杂谈 2023年7月24日
    069
  • PageHelper的使用

    PageHelper pagehelper是mybatis的一个插件,其作用是更加方便地进行分页查询 分页查询的实现有两种方式 1:直接在sql中使用 limit子句 进行分页查询…

    技术杂谈 2023年5月31日
    0111
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球