算法打卡day19

今日任务:

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 = xself.left = Noneself.right = Noneclass 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 rootwhile root:if root.val > p.val and root.val > q.val:root = root.leftelif root.val < p.val and root.val < q.val:root = root.rightelse: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.leftelif root.val < p.val and root.val < q.val:root = root.rightelse:breakreturn 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.leftelse:if node.right is None:node.right = TreeNode(val)breakelse:node = node.rightreturn 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 = valself.left = leftself.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.rightwhile cur.left is not None:cur = cur.leftcur.left = root.leftreturn root.rightif 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.mzph.cn/news/775139.shtml

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

相关文章

kafka-eagle 配置文件修改使用自带的数据库

###################################### multi zookeeper & kafka cluster list Settings prefixed with ‘kafka.eagle.’ will be deprecated, use ‘efak.’ instead ###################################### efak.zk.cluster.aliascluster1 #cluster1.zk.listip1:…

javaScript【2】

在 JavaScript 中&#xff0c;let、var 和 const 是用于声明变量的关键字&#xff0c;它们之间有一些区别。 var&#xff1a;var 是 JavaScript 最早引入的变量声明关键字。使用 var 声明的变量具有函数作用域&#xff0c;意味着变量在声明它的函数内可见。如果在函数内部使用…

Adobe推出20多个,企业版生成式AI定制、微调服务

3月27日&#xff0c;全球多媒体领导者Adobe在拉斯维加斯召开“Summit 2024”大会&#xff0c;重磅推出了Firefly Services。 Firefly Services提供了20 多个生成式AI和创意API服务&#xff0c;支持企业自有数据对模型进行定制、微调&#xff0c;同时可以与PS、Illustrator、Ex…

华为开源自研AI框架昇思MindSpore应用案例:梯度累加

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、案例实现 梯度累加的训练算法&#xff0c;目的是为了解决由于内存不足&#xff0c;导致Batch size过大神经网络无法训练&#xff0c;或者网络模型过大无法加载的OOM&#xff08;Out Of Memory&#xff…

Learn OpenGL 26 视差贴图

什么是视差贴图 视差贴图(Parallax Mapping)技术和法线贴图差不多&#xff0c;但它有着不同的原则。和法线贴图一样视差贴图能够极大提升表面细节&#xff0c;使之具有深度感。它也是利用了视错觉&#xff0c;然而对深度有着更好的表达&#xff0c;与法线贴图一起用能够产生难…

uniapp写小程序如何实现分包

众所众知小程序上传的过程中对包的大小有限制&#xff0c;正常情况下不允许当个包超过2M&#xff0c;所以需要分包 需要再pages.json这个文件夹中进行配置 "pages": [{"path": "pages/index/index","style": {"navigationBarTit…

备考ICA----Istio实验11---为多个主机配置TLS Istio Ingress Gateway实验

备考ICA----Istio实验11—为多个主机配置TLS Istio Ingress Gateway实验 1. 部署应用 kubectl apply -f istio/samples/helloworld/helloworld.yaml -l servicehelloworld kubectl apply -f istio/samples/helloworld/helloworld.yaml -l versionv12. 证书准备 接上一个实验…

Hive常用函数之字符串处理

Hive常用函数之字符串处理 以下是Hive中常用的字符串处理函数&#xff0c;可用于执行各种字符串处理转换操作。 1. CONCAT()&#xff1a;将多个字符串连接在一起。 SELECT CONCAT(Hello, World); -- Output: HelloWorld2. SUBSTR()&#xff1a;从字符串中提取子字符串&#xf…

【备忘录】Linux系统安全限制:禁用或限制用户ssh登录

查看失败的IP iplist$(/bin/lastb |awk {print $3}|sort|uniq -c|awk {if ($1>1500) print $2} | grep -v "^10.0.0.") 并将ip追加到黑名单 for ip in ${iplist} doecho ALL: ${ip} >> /etc/hosts.deny# sshd 失败ip追加到黑名单echo "sshd:112.192.…

计算机网络:物理层 - 信道复用

计算机网络&#xff1a;物理层 - 信道复用 频分复用时分复用统计时分复用波分复用码分复用 计算机网络中&#xff0c;用户之间通过信道进行通信&#xff0c;但是信道是有限的&#xff0c;想要提高网络的效率&#xff0c;就需要提高信道的利用效率。因此计算机网络中普遍采用信道…

笔记本作为其他主机显示屏(HDMI采集器)

前言&#xff1a; 我打算打笔记本作为显示屏来用&#xff0c;连上工控机&#xff0c;这不是贼方便吗 操作&#xff1a; 一、必需品 HDMI采集器一个 可以去绿联买一个&#xff0c;便宜的就行&#xff0c;我的大概就长这样 win10下载 PotPlayer 软件 下载链接&#xff1a;h…

【微服务篇】深入理解微服务网关原理以及Spring Gateway

微服务网关的作用 微服务网关在微服务架构中扮演着至关重要的角色&#xff0c;它主要负责请求的路由、组成服务间的通信桥梁、聚合不同服务的数据以及提供跨服务的统一认证机制。以下是微服务网关的几个主要作用&#xff1a; 请求路由: 微服务网关充当所有入站请求的入口点&a…

PHP - ZipArchive上传、下载实例

概述 在很多实际生产场景都需要批量上传、下载一些文件的处理&#xff0c;整理了使用PHP语言操作ZipArchive实践和实例&#xff0c;ZipArchive需要服务器上安装zlib库&#xff0c;php扩展中安装zip扩展。 服务器环境扩展 ZipArchive类库的PHP版本要求如下&#xff0c;另外ph…

ClickHouse11-ClickHouse中文件引擎与物化视图的组合拳

全文概览&#xff1a; 什么是物化视图 使用场景 如何实现这个需求 建立一个使用表引擎的表&#xff0c;作为物化视图的目标表确定需要查询的SQL创建物化视图测试 文件引擎其实是一个不常用的特殊表引擎&#xff0c;结合【ClickHouse09-表引擎之文件引擎】一章节的基础介绍 这…

Flutter 常用插件Plugin整理并附带实例

最近有点空闲时间&#xff0c;正好写一篇文章&#xff0c;整理一下我们在Flutter开发中常用的插件Plugin使用并附带上实例。 在日常开发中&#xff0c;整个demo目前应该满足大家所有的开发需求&#xff0c;例如&#xff1a;http请求、列表刷新及加载、列表分组、轮播图、视频播…

AI浪潮席卷游戏业:未来5~10年,游戏或将由AI生成

一年前&#xff0c;因为AI失业的第一批人&#xff0c;在游戏行业出现了。游戏原画、翻译等外包团队开始遭遇砍单&#xff0c;AI绘画工具的发展速度和水平已经几乎可以媲美科班出身、初级经验的人类画师。 一年时间过去&#xff0c;在游戏制作的毛细血管中&#xff0c;越来越多…

SpringBoot3的RabbitMQ消息服务

目录 预备工作和配置 1.发送消息 实现类 控制层 效果 2.收消息 3.异步读取 效果 4.Work queues --工作队列模式 创建队列text2 实体类 效果 5.Subscribe--发布订阅模式 效果 6.Routing--路由模式 效果 7.Topics--通配符模式 效果 异步处理、应用解耦、流量削…

The C programming language (second edition,KR) exercise(CHAPTER 1)

E x c e r c i s e 1 − 2 Excercise\quad 1-2 Excercise1−2&#xff1a;测试结果如图1所示&#xff0c;这里需要注意的是转义字符序列 \ o o o \backslash ooo \ooo和序列 \ x h h \backslash xhh \xhh分别表示3个八进制数和2个十进制数对应的值对应于 A S C I I ASCII ASCII…

Django Cookie和Session

Django Cookie和Session 【一】介绍 【1】起因 HTTP协议四大特性 基于请求响应模式&#xff1a;客户端发送请求&#xff0c;服务端返回响应基于TCP/IP之上&#xff1a;作用于应用层之上的协议无状态&#xff1a;HTTP协议本身不保存客户端信息短链接&#xff1a;1.0默认使用短…

python asyncio websockets server

python websocket server在收到接受消息处理完后会默认关闭连接。需要在msg_handler里面加个while true就能一直保持连接了。 start_server websockets.serve(msg_handler, "0.0.0.0", 29967) asyncio.get_event_loop().run_until_complete(start_server) asyncio.…