算法打卡day19

news2024/11/18 5:47:51

今日任务:

1)235. 二叉搜索树的最近公共祖先

2)701.二叉搜索树中的插入操作

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

235. 二叉搜索树的最近公共祖先

题目链接:235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。

文章讲解:代码随想录 (programmercarl.com)

视频讲解:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先哔哩哔哩bilibili

思路:

这题与昨天打卡的236.二叉树的最近公共祖先这题比较像

在236题中提到

如果某节点node为p,q的最近公共祖先,那么p,q会出现以下三种情况:

1.p 和 q 在 node 的子树中,且分列 node 的异侧(即分别在左、右子树中);
2.p=node,且 q 在 node 的左或右子树中;
3.q=node,且 p 在 node 的左或右子树中;

在236题中是普通二叉树,没有顺序,所以我们需要按顺序遍历节点找到p,q

在今天这题中,我们可以利用搜索二叉树的特点

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

所以我们通过比较p,q,与当前节点的大小即可快速找p,q

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    def lowestCommonAncestor2(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 如果p,q同在左侧,则继续往左子树找
        if root.val > p.val and root.val > q.val:
            return self.lowestCommonAncestor(root.left, p, q)
        
        # 如果p,q同在右侧,则继续往右子树找
        elif root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right, p, q)

        # q,p在异侧,则返回当前节点;或者root为空,返回空(返回root也就是返回空)
        else:
            return root

这题也可以使用迭代法,因为搜索二叉树有序,不存在回溯

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return root
        while root:
            if root.val > p.val and root.val > q.val:
                root = root.left
            elif root.val < p.val and root.val < q.val:
                root = root.right
            else:
                return root

    # 改进
    def lowestCommonAncestor2(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        while root:
            if root.val > p.val and root.val > q.val:
                root = root.left
            elif root.val < p.val and root.val < q.val:
                root = root.right
            else:
                break
        return root

701.二叉搜索树中的插入操作

题目链接:701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。

文章讲解:代码随想录 (programmercarl.com)

视频讲解:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作哔哩哔哩bilibili

思路:

我们不考虑题目中提示所说的改变树的结构的插入方式,插入值一定可以找到合适的叶子节点位置

实现过程:

1)只要按照二叉搜索树的规则去遍历,当遇到空节点时,也就是我们要插入的位置,我们返回插入点即可。此时还不知道是左节点还是右节点。

2)判断插入值和当前节点的大小,如果小于当前节点,则表明应该是当前节点的左孩子接受返回值

3)如果大于当前节点,则表明应该是当前节点的右孩子接受返回值

4)最后返回root即可(如果根节点本身为空,则出现我们第一步,返回插入点)

class Solution2:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        # 当遇到空节点时,则将插入值变为节点
        if not root:
            root = TreeNode(val)
            return root

        # 如果当前节点大于插入节点值,则将插入值赋给当前节点的左孩子
        if root.val > val:
            root.left = self.insertIntoBST(root.left, val)

        # 如果当前节点小于插入节点值,则将插入值赋给当前节点的右孩子
        if root.val < val:
            root.right = self.insertIntoBST(root.right, val)

        return root

也可以用迭代法,思路与之前一样,这里我是在判断过程中就赋予了值,成功插入即返回结果。

class Solution3:
    def insertIntoBST(self, root, val):
        if root is None:  # 如果根节点为空,创建新节点作为根节点并返回
            node = TreeNode(val)
            return node

        # 如果节点不为空,一直遍历直到找到空节点
        node = root  # 最后要返回根节点,为了不改变root,重新定一个变量
        while node:
            if node.val > val:
                if node.left is None:
                    node.left = TreeNode(val)
                    break  # 找到则跳出循环
                else:
                    node = node.left
            else:
                if node.right is None:
                    node.right = TreeNode(val)
                    break
                else:
                    node = node.right

        return root

代码随想录提供的代码是采用两个指针记录的当前节点与父节点,当前节点为空时,则找到插入点,比较父节点与插入值大小,将父节点指向插入值即可,详细代码见代码随想录

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

题目链接:450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

文章讲解:代码随想录 (programmercarl.com)

视频讲解:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点哔哩哔哩bilibili

思路:

这题比较有意思,不像插入节点,直接插入到叶子节点,这题删除一个节点,可能会导致树的结构变化

二叉搜索树中删除节点遇到的情况都搞清楚。

有以下五种情况:

  • 找到删除的节点
    • 第一种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
    • 第二种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    • 第三种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    • 第四种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
  • 第五种情况:没找到删除的节点,遍历到空节点直接返回了

第四种情况比较复杂,删除节点左不空右不空,将右子树继位(也可以左子树继位)。我们需要将删除节点的左子树,给移到右子树上。根据搜索二叉树的特性,应该把左子树移到右子树左底层(只有左底层是略微大于删除节点的,左子树是略微小于删除节点,所以应该把左子树放到右子树的左底层)。然后再将上上节点指向当前节点

动画中的二叉搜索树中,删除元素7, 那么删除节点(元素7)的左孩子就是5,删除节点(元素7)的右子树的最左面节点是元素8。

将删除节点(元素7)的左孩子放到删除节点(元素7)的右子树的最左面节点(元素8)的左孩子上,就是把5为根节点的子树移到了8的左孩子的位置。

要删除的节点(元素7)的右孩子(元素9)为新的根节点。.

这样就完成删除元素7的逻辑,

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        # 如果节点为空
        if not root:
            return root

        # 找到删除节点
        if root.val == key:
            # 情况一:删除节点左空右空(即跟节点),直接删除,返回空值
            if root.left is None and root.right is None:
                return None
            # 情况二:删除节点左空右不空,将右节点返回
            elif root.left is None:
                return root.right
            # 情况三:删除节点左不空右空,将左节点返回
            elif root.right is None:
                return root.left
            # 情况四:删除节点左不空右不空,将右子树继位(也可以左子树继位)
            # 将删除节点的左子树,给移到右子树上。根据搜索二叉树的特性,应该把左子树移到右子树左底层(只有左底层是略微大于删除节点的,左子树是略微小于删除节点,所以应该把左子树放到右子树的左底层)
            else:
                cur = root.right
                while cur.left is not None:
                    cur = cur.left
                cur.left = root.left
                return root.right

        if root.val > key:
            root.left = self.deleteNode(root.left, key)
        if root.val < key:
            root.right = self.deleteNode(root.right, key)
        return root

感想:多做多做多做!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1550262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql数据库——高级SQL语句补充

目录 一、子查询——Subquery 1.环境准备 2.In——查询已知的值的数据记录 2.1子查询——Insert 2.2子查询——Update 2.3子查询——Delete 3.Not In——表示否定&#xff0c;不在子查询的结果集里 3.Exists——判断查询结果集是否为空 4.子查询——别名 二、视图—…

政安晨:【Keras机器学习实践要点】(六)—— 使用内置方法进行训练和评估

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本文涵盖使用内置 API 进行训练和验证&#…

pytorch+tensorboard

安装依赖 pip install teorboard pip install torch_tb_profiler了解teorboard 记录并可视化标量[组]、图片[组]。 如何使用 第一步&#xff1a;构建模型&#xff0c;记录中间值&#xff0c;写入summarywriter 每次写入一个标量add_scalar 比如&#xff1a; from torch.u…

深度学习:基于PyTorch的模型解释工具Captum

深度学习&#xff1a;基于PyTorch的模型解释工具Captum 引言简介示例安装解释模型的预测解释文本模型情绪分析问答 解释视觉模型特征分析特征消融鲁棒性 解释多模态模型 引言 当我们训练神经网络模型时&#xff0c;我们通常只关注模型的整体性能&#xff0c;例如准确率或损失函…

上位机图像处理和嵌入式模块部署(qmacvisual区域提取)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在图像处理中&#xff0c;有两部分比较重要&#xff0c;一个是区域分割&#xff0c;一个是区域提取。区域分割&#xff0c;比较好理解&#xff0c;…

Chrome 插件 storage API 解析

Chrome.storage API 解析 使用 chrome.storage API 存储、检索和跟踪用户数据的更改 一、各模块中的 chrome.storage 内容 1. Service worker 中 runtime 内容 2. Action 中 runtime 内容 3. Content 中 runtime 内容 二、权限&#xff08;Permissions&#xff09; 如果需使…

SPU赋能PSI:探秘隐私集合求交核心技术与高级调度架构实践

1.SPU实现的PSI介绍 1.PSI的定义和种类 隐私集合求交&#xff08;Private Set Intersection, PSI&#xff09;是一种在密码学和安全多方计算&#xff08;MPC&#xff09;领域中的关键技术&#xff0c;允许两个或多个参与者在不泄露各自输入集合中非交集部分的前提下&#xff…

【python分析实战】成本:揭示电商平台月度开支与成本结构占比 - 过于详细 【收藏】

重点关注本文思路&#xff0c;用python分析&#xff0c;方便大家实验复现&#xff0c;代码每次都用全量的&#xff0c;其他工具自行选择。 全文3000字&#xff0c;阅读10min&#xff0c;操作1小时 企业案例实战欢迎关注专栏 每日更新&#xff1a;https://blog.csdn.net/cciehl/…

深入理解element-plus table二次封装:从理论到实践的全面指南

前言 在许多中后台管理系统中&#xff0c;表格占据着半壁江山&#xff0c;如果使用element plus组件库&#xff0c;那么少不了要用到table组件&#xff0c;可是table组件的功能过于基础&#xff0c;因此&#xff0c;我在table组件的实现基础之上进一步封装&#xff0c;从而实现…

2024-03-24 需求分析-智能问答系统-调研

一. 需求列表 基于本地知识库的问答系统对接外围系统 数字人语音识别二. 待调研的公司 2.1 音视贝 AI智能外呼_大模型智能客服系统_大模型知识库系统_杭州音视贝 (yinshibei.com) 2.2 得助智能 智能AI客服机器人-智能电话机器人客服-电话电销机器人-得助智能 (51ima.com) 2…

【LVGL-使用SquareLine Studio设计器 】

LVGL-使用SquareLine Studio设计器 ■ 简介■ 安装■ SquareLine Studio移植到工程 ■ 简介 SquareLine Studio 设计器是一个付费软件。 ■ 安装 SquareLine Studio 设计器的下载地址 我们点击“WINDOWS”下载 SquareLine Studio 设计器&#xff0c;下载完成之后我们就会得到…

ActiveMQ Artemis 系列| High Availability 主备模式(消息复制) 版本2.19.1

一、ActiveMQ Artemis 介绍 Apache ActiveMQ Artemis 是一个高性能的开源消息代理&#xff0c;它完全符合 Java Message Service (JMS) 2.0 规范&#xff0c;并支持多种通信协议&#xff0c;包括 AMQP、MQTT、STOMP 和 OpenWire 等。ActiveMQ Artemis 由 Apache Software Foun…

Android 性能优化实例分享-内存优化 兼顾效率与性能

背景 项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率&#xff0c;做了内存优化和下载导出优化&#xff0c;具体效果如最后的一节的表格所示。 下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍&#xff1a; 一.拍摄前预览页面优化 预览效果问题 存在…

快速上手Spring Cloud 十一:微服务架构下的安全与权限管理

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …

vuees6新语法

vue的学习网站&#xff1a; https://www.runoob.com/vue2/vue-tutorial.html1.Vue的介绍 学习目标 说出什么是Vue能够说出Vue的好处能够说出Vue的特点 内容讲解 【1】Vue介绍 1.vue属于一个前端框架&#xff0c;底层使用原生js编写的。主要用来进行前端和后台服务器之间的…

搜索插入位置-java

题目描述 : 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 思路分析: 这段代码的解题思想是利用二分查找的方法在…

微服务(基础篇-006-Docker安装-CentOS7)

目录 05-初识Docker-Docker的安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p46&spm_id_frompageDriver&vd_source60a35a11f813c6dff0b76089e5e138cc 0.安装Docker 1.CentOS安装Docker 1.1.卸载&#xff08;可选&#xff09; 1.2.安装dock…

爬虫工作量由小到大的思维转变---<第六十章 Scrapy框架中的信号处理机制(Signals)研究(1)>

前言: Scrapy框架默认的事件驱动设计在某些场景下可能不够灵活或满足定制化需求。因此&#xff0c;深入研究Scrapy框架中的信号处理机制&#xff08;Signals&#xff09;是必要的。 本研究的目的是深入了解Scrapy框架中的信号处理机制&#xff0c;在网络爬虫中的应用和意义。通…

软考高级架构师:ESB 企业服务总线概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

正则表达式 vs. 字符串处理:解析优势与劣势

title: 正则表达式 vs. 字符串处理&#xff1a;解析优势与劣势 date: 2024/3/27 15:58:40 updated: 2024/3/27 15:58:40 tags: 正则起源正则原理模式匹配优劣分析文本处理性能比较编程应用 1. 正则表达式起源与演变 正则表达式&#xff08;Regular Expression&#xff09;最早…