当前位置: 首页 > news >正文

代码随想录算法训练营第十六天| 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

写代码的第十六天,自从到了二叉树错误版代码就少了,因为我自己根本没思路,都是看完思路在做,那基本上就是小语法问题,很少有其他问题了,证实了我好菜。。。。。。
还是得写思路啊啊啊啊,写思路好重要!!!

530.二叉搜索树的最小绝对差

思路

看见二叉搜索树,首先可以想到中序遍历,就变成了一个有序的数组,在数组中求相邻两个元素的最小绝对差。

class Solution:def getMinimumDifference(self, root: Optional[TreeNode]) -> int:mindif = float('inf')res = []self.traversal(root,res)for i in range(1,len(res)):diff = res[i] - res[i-1]mindif = min(mindif, diff)return mindifdef traversal(self,root,res):if root == None:return left = self.traversal(root.left,res)res.append(root.val)right = self.traversal(root.right,res)return res

思路(双指针)

要计算任意两个结点的最小值,还是按照左中右这样的顺序,因为这样计算的话每次都是从小到大的顺序,计算差值肯定相邻的一定比不相邻的小,在最开始我一直觉得万一最后一个数和第一个数的差值比其他的都小呢,其实这种情况根本不可能存在,就像上面的数组,最后一个数减去第一个数的差值不可能比他相邻的数减去第一个数的差值小。所以在这里设置两个结点变量,一个指向当前结点,一个指向当前结点的前一个结点,这两个结点都进行中序遍历,对这两个结点做减法,记录最小值,然后递归的进行中序遍历不断的判断,这个时候记录最小值的变量就应该设置为全局变量了,因为要存储最后的最小值,而不是每次递归都给他初始化成同一个值,它需要被记录。
正确代码

class Solution:def __init__(self):self.mindif = float('inf')self.pre = Nonedef getMinimumDifference(self, root: Optional[TreeNode]) -> int:self.traversal(root)return self.mindifdef traversal(self,cur):if cur == None:returnself.traversal(cur.left)if self.pre != None:self.mindif = min(cur.val - self.pre.val,self.mindif)self.pre = curself.traversal(cur.right)

总结一下全局变量这一块,之前一直不知道全局变量用在哪,但是连着做了三四个题,我理解的全局变量就是在所有函数中进行操作这个变量他的值都会被存下来,会改变。如果放在函数体内的局部变量尤其是在递归的时候每次都会重复调用,如果像之前一样总是设置为0或者1这种,那么每次递归都从0或者1开始,肯定会报错。

501.二叉搜索树中的众数

思路

使用中序遍历(但其实好像哪种遍历都行,因为最后生成的是字典,不需要非得有序),在遍历过程中直接构建字典,然后遍历字典输出最大的那个value。
注释:如果你想将字典中所有键的初始值都设置为0,但不知道具体的键有哪些,你可以使用默认字典(defaultdict)来实现。defaultdict 是 collections 模块中的一个类,它是字典的一个子类,可以提供默认值来初始化字典中的键。

from collections import defaultdict
my_dict = defaultdict(lambda: 0)

错误第一版:第一处错误是在使用 defaultdict 初始化 mapdict 时,需要指定默认值的类型。你可以将 int 作为默认值类型,表示键的初始值为0。第二处错误是在遍历 mapdict 的键值对时,需要使用 items() 方法来获取键值对的迭代器,然后才能进行迭代。第三处错误是在 findMode() 方法中的 if root == None 分支中,你返回的是 None,而函数的返回类型应该是 List[int]。你可以返回一个空列表 [] 来表示没有找到任何模式。

from collections import defaultdict
class Solution:def findMode(self, root: Optional[TreeNode]) -> List[int]:result = []mapdict = defaultdict()if root == None:return self.searchBFS(root,mapdict)maxval = max(mapdict.values())for k,v in mapdict:if v == maxval:result.append(k)return resultdef searchBFS(self,root,mapdict):if root == None:return self.searchBFS(root.left,mapdict)mapdict[root.val] += 1self.searchBFS(root.right,mapdict)

正确代码

from collections import defaultdict
class Solution:def findMode(self, root: Optional[TreeNode]) -> List[int]:result = []mapdict = defaultdict(int)if root == None:return []self.searchBFS(root,mapdict)maxval = max(mapdict.values())for k,v in mapdict.items():if v == maxval:result.append(k)return resultdef searchBFS(self,root,mapdict):if root == None:return self.searchBFS(root.left,mapdict)mapdict[root.val] += 1self.searchBFS(root.right,mapdict)

需要注意的一个地方是,众数可以有很多个,所以设置了result来存放。

思路(指针)

拿过来自己没思路,这个情况很烦啊,我一直想不通遍历的话不还是变成数组这样才能比较吗,指针就算是设置为一个cur一个pre和上面题一样也做不出来啊,怎么就判断这个是众数呢,就算判断了你怎么计数呢?这些问题我无法解决,我好痛苦。看了一下卡哥的思路,也是设置cur和pre两个指针,采用中序遍历,pre一直在cur前面,他俩永远是相邻的,只要判断这两个指针相等,那么这个数就出现了不止一次就可以说是众数,将其append进结果集中,但是如果当前遍历的众数出现了两次,但是之后有众数出现了三次,这种情况怎么解决呢,把当前结果集清空,然后将现在的结果append进结果姐,第一个问题解决了。那现在怎么计数呢,当出现pre和cur的值是相等的时候,count计数器加一,一旦pre和cur不相等count直接变成1,重新从1开始计数。记得要更新pre。
现在来解决递归的三个基本条件:
解决问题1:参数和返回值?我们设置了存储最后众数的结果集,pre指针,但是这些都已经设置在全局变量中了,所以参数只需要cur。因为要遍历完整颗树并不需要在过程中停止,所以不需要返回值,同时需要修改的值已经在全局变量中设置好了,也不需要返回。
解决问题2:终止条件?当cur为空的时候,就证明树遍历结束了,但是我们不需要返回值,所以return就行。
解决问题3:单层递归逻辑?pre在cur前面,不停的比较cur和pre的值,如果相等,将这个值append进result中,count也就是出现次数加一;当pre不等与cur的值的时候将count的值赋值给maxcount,然后将count=1,用这一步把现在出现的众数的出现最大次数计数,更新maxcount;然后继续遍历继续找,如果有出现count大于maxcount的情况的时候就把result全部清空,然后将新的这个结点的值append进result中,更新maxcount,直到终止条件。
错误第一版

from collections import defaultdict
class Solution:def __init__(self):self.pre = Noneself.result = []self.count = 1self.maxcount = float('-inf')def traversal(self,cur):if cur == None:return self.traversal(cur.left)if self.pre != None and self.pre.val == cur.val:self.count += 1self.result.append(cur.val)if self.pre != None and self.pre.val != cur.val:self.maxcount = self.countself.count = 1if self.count > self.maxcount:self.result.clear()self.result.append(cur.val)self.traversal(cur.right)def findMode(self, root: Optional[TreeNode]) -> List[int]:self.traversal(root)return self.result

再次整理思路:只看单次递归这里,先计数在和maxcount比较,然后再决定要不要进result。如果pre和cur的值相等那么count+1,如果不相等,那么count=1;然后再将count和maxcount进行比较,如果count等于maxcount,那么将当前的结点值append进result,如果count小于maxcount不做任何操作,如果count大于maxcount那么更新maxcount = count并且将result全部清空,然后将现在的值append进result。
正确代码

from collections import defaultdict
class Solution:def __init__(self):self.pre = Noneself.result = []self.count = 1self.maxcount = 0def traversal(self,cur):if cur == None:return self.traversal(cur.left)if self.pre != None and self.pre.val == cur.val:self.count += 1if self.pre != None and self.pre.val != cur.val:self.count = 1self.pre = curif self.count == self.maxcount:self.result.append(cur.val)if self.count > self.maxcount:self.maxcount = self.countself.result.clear()  # 先清空 result 列表self.result.append(cur.val)self.traversal(cur.right)def findMode(self, root: Optional[TreeNode]) -> List[int]:self.traversal(root)return self.result

236. 二叉树的最近公共祖先

思路

因为是想找最近公共祖先,所以后序遍历最好。(没审题我真的会谢,我一直挣扎与万一p或者q不在这个树中咋办啊,结果题里面写了p 和 q 均存在于给定的二叉树中,我真该啊。。。)
解决问题1:参数和返回值是什么?在本题中参数是root以及p和q两个结点,返回值就是最近公共祖先。
解决问题2:终止条件是什么?如果在遍历的过程中在左子树出现q右子树出现p或者左子树出现p右子树出现q那么就说明公共祖先存在,返回此时左右子树的上一个,也就是左右中遍历的中结点;如果遍历了整颗树(也就是root==None的情况)只存在一个或者两个都不存在,那么返回None,没有公共祖先。
解决问题3:单次递归的逻辑是什么?根据下面的解释,本题中单次递归是左右都需要遍历的,并且需要返回值的。按照后序遍历左右中的情况,先递归左子树,然后递归右子树,最后处理中结点,其实中结点是我们的主要处理位置。中结点需要判断的是其左右子树是否存在q和p,如果两个都存在,那么向上一层返回
补充:这个部分是我经常会产生疑问的,卡哥说的非常清晰,记一下嘿嘿嘿。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
错误第一版:就因为挣扎于万一有p或者q不在树中怎么办,其实题中说的很明确了,q和p一定存在。错误是解答错误,思路还是有点问题。

class Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':if root == None:return  left = self.lowestCommonAncestor(root.left,p,q)right = self.lowestCommonAncestor(root.right,p,q)if left != None and right == None:return rightelif left == None and right != None:return leftelse:return root

重新整理思路:在终止条件这里,一种情况是遍历完整颗树也就是root==None的时候那么返回root其实也就是None(需要注意一下我之前理解的终止条件总以为是最后的输出值,其实不是,他就只是最后一次递归的值,我们还要回溯回去呢),第二种情况就是当root结点就是q或者p的时候根据题意p和q是一定存在的,那么当前已经遍历到了q或者p那就证明剩下的那个一定在他下面的树中,所以q或者p就是他们自己的公共祖先。再说一下单次递归这里,如果遍历了left和right但是这两个里面都是有返回值的,也就是存在p或q那么就直接返回root也就是他们的上一个结点,如果只有left或者right有值,那就证明p和q存在于一侧,所以只返回那一侧就可以了,如果遍历完成了没有任何一个地方存在,那就返回None。
正确代码

class Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':if root == None:return rootif root == q or root == p:return rootleft = self.lowestCommonAncestor(root.left,p,q)right = self.lowestCommonAncestor(root.right,p,q)if left != None and right == None:return leftelif left == None and right != None:return rightelif left != None and right != None:return rootelse:return None

相关文章:

代码随想录算法训练营第十六天| 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

写代码的第十六天,自从到了二叉树错误版代码就少了,因为我自己根本没思路,都是看完思路在做,那基本上就是小语法问题,很少有其他问题了,证实了我好菜。。。。。。 还是得写思路啊啊啊啊,写思路好…...

NODEJS复习(ctfshow334-344)

NODEJS复习 web334 下载源码代码审计 发现账号密码 代码逻辑 var findUser function(name, password){ return users.find(function(item){ return name!CTFSHOW && item.username name.toUpperCase() && item.password password; }); }; 名字不等于ctf…...

【Go系列】RPC和grpc

承上启下 介绍完了Go怎么实现RESTFul api,不可避免的,今天必须得整一下rpc这个概念。rpc是什么呢,很多人都想把rpc和http一起对比,但是他们不是一个概念。RPC是一种思想,可以基于tcp,可以基于udp也可以基于…...

【VUE】v-if和v-for的优先级

v-if和v-for v-if 用来显示和隐藏元素 flag为true时&#xff0c;dom元素会被删除达到隐藏效果 <div class"boxIf" v-if"flag"></div>v-for用来进行遍历&#xff0c;可以遍历数字对象数组&#xff0c;会将整个元素遍历指定次数 <!-- 遍…...

【单目3D检测】smoke(1):模型方案详解

纵目发表的这篇单目3D目标检测论文不同于以往用2D预选框建立3D信息&#xff0c;而是采取直接回归3D信息&#xff0c;这种思路简单又高效&#xff0c;并不需要复杂的前后处理&#xff0c;而且是一种one stage方法&#xff0c;对于实际业务部署也很友好。 题目&#xff1a;SMOKE&…...

数据库系统概论:数据库系统的锁机制

引言 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;数据作为一种共享资源&#xff0c;其并发访问的一致性和有效性是数据库必须解决的问题。锁机制通过对数据库中的数据对象&#xff08;如表、行等&#xff09;进行加锁&#xff0c;以确保在同…...

Django+vue自动化测试平台(28)-- ADB获取设备信息

概述 adb的全称为Android Debug Bridge&#xff0c;就是起到调试桥的作用。通过adb可以在Eclipse中通过DDMS来调试Android程序&#xff0c;说白了就是调试工具。 adb的工作方式比较特殊&#xff0c;采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯&#xff0c;默认情况下…...

RESTful API设计指南:构建高效、可扩展和易用的API

文章目录 引言一、RESTful API概述1.1 什么是RESTful API1.2 RESTful API的重要性 二、RESTful API的基本原则2.1 资源导向设计2.2 HTTP方法的正确使用 三、URL设计3.1 使用名词而非动词3.2 使用复数形式表示资源集合 四、请求和响应设计4.1 HTTP状态码4.2 响应格式4.2.1 响应实…...

npm下载的依赖包版本号怎么看

npm下载的依赖包版本号怎么看 版本号一般分三个部分&#xff0c;主版本号、次版本号、补丁版本号。 主版本号&#xff1a;一般依赖包发生重大更新时&#xff0c;主版本号才回发生变化&#xff0c;如Vue2.x到Vue3.x。次版本号&#xff1a;当依赖包中发生了一些小变化&#xff…...

css前端面试题

1.什么是css盒子模型&#xff1f; 盒子模型包含了元素内容&#xff08;content&#xff09;、内边距&#xff08;padding&#xff09;、边框&#xff08;border&#xff09;、外边距&#xff08;margin&#xff09;几个要素。 标准盒子模型和IE盒子模型的区别在于其对元素的w…...

Vue从零到实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…...

【Chatgpt大语言模型医学领域中如何应用】

随着人工智能技术 AI 的不断发展和应用&#xff0c;ChatGPT 作为一种强大的自然语言处理技术&#xff0c;无论是 自然语言处理、对话系统、机器翻译、内容生成、图像生成&#xff0c;还是语音识别、计算机视觉等方面&#xff0c;ChatGPT 都有着广泛的应用前景。特别在临床医学领…...

ES6 正则的扩展(十九)

1. 正则表达式字面量改进 特性&#xff1a;在 ES6 中&#xff0c;正则表达式字面量允许在字符串中使用斜杠&#xff08;/&#xff09;作为分隔符。 用法&#xff1a;简化正则表达式的书写。 const regex1 /foo/; const regex2 /foo/g; // 全局搜索2. u 修饰符&#xff08;U…...

<数据集>钢铁缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1800张 标注数量(xml文件个数)&#xff1a;1800 标注数量(txt文件个数)&#xff1a;1800 标注类别数&#xff1a;6 标注类别名称&#xff1a;[crazing, patches, inclusion, pitted_surface, rolled-in_scale, scr…...

Kafka系列之:Kafka存储数据相关重要参数理解

Kafka系列之:Kafka存储数据相关重要参数理解 一、log.segment.bytes二、log.retention.bytes三、日志段四、log.retention.check.interval.ms五、数据底层文件六、index、log、snapshot、timeindex、leader-epoch-checkpoint、partition.metadata一、log.segment.bytes 参数lo…...

Template execution failed: ReferenceError: name is not defined

问题 我们使用了html-webpack-plugin&#xff08;webpack&#xff09;进行编译html&#xff0c;导致的错误。 排查结果 连接地址 html-webpack-plugin版本低(2.30.1)&#xff0c;html模板里面不能有符号&#xff0c;注释都不行 // var reg new RegExp((^|&)${name}([^&…...

CVE-2024-24549 Apache Tomcat - Denial of Service

https://lists.apache.org/thread/4c50rmomhbbsdgfjsgwlb51xdwfjdcvg Apache Tomcat输入验证错误漏洞&#xff0c;HTTP/2请求的输入验证不正确&#xff0c;会导致拒绝服务&#xff0c;可以借助该漏洞攻击服务器。 https://mvnrepository.com/artifact/org.apache.tomcat.embed/…...

Linux下如何安装配置Graylog日志管理工具

Graylog是一个开源的日志管理工具&#xff0c;可以帮助我们收集、存储和分析大量的日志数据。它提供了强大的搜索、过滤和可视化功能&#xff0c;可以帮助我们轻松地监控系统和应用程序的运行情况。 在Linux系统下安装和配置Graylog主要包括以下几个步骤&#xff1a; 准备安装…...

「MQTT over QUIC」与「MQTT over TCP」与 「TCP 」通信测试报告

一、结论 在实车5G测试中「MQTT Over QUIC」整体表现优于「TCP」&#xff0c;可在系统架构升级时采用MQTT Over QUIC替换原有的TCP通讯&#xff1b;从实现原理上基于QUIC比基于TCP在弱网、网络抖动导致频繁重连场景延迟更低。 二、测试方案 网络类型&#xff1a;实车5G、实车…...

获取磁盘剩余容量-----c++

获取磁盘剩余容量 #include <filesystem>struct DiskSpaceInfo {double total;double free;double available; };DiskSpaceInfo getDiskSpace(const std::string& path) {std::filesystem::space_info si std::filesystem::space(path);DiskSpaceInfo info;info.…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...