【代码随想录训练营】【Day19休息】【Day20】第六章|二叉树|654.最大二叉树|617.合并二叉树|700.二叉搜索树中的搜索|98.验证二叉搜索树
最大二叉树
题目详细:LeetCode.654
这道题在题目几乎就说明了解题的思路了:
- 创建一个根节点,其值为 nums 中的最大值;
- 递归地在最大值左边的子数组上构建左子树;
- 递归地在最大值右边的子数组上构建右子树;
- 返回 nums 构建的 最大二叉树 。
显而易见,我可以把构建最大二叉树这个大问题,划分为一个个小问题,当每一棵子树都按照上述思路来构建,那么整体就构成了一棵最大二叉树,小问题思路如下:
- 数组 nums 有三种情况:
- 数组长度为0:说明节点序列为空,返回 null
- 数组长度为1:说明只有一个节点,构建并返回节点
- 数组长度 > 1:找出最大值来构建当前节点
- 找出nums中的最大值,以及最大值的下标
- 按照要求,通过最大值的下标来划分构建左右子树的子数组
- 左子树通过最大值左边的子数组来构建
- 右子树通过最大值右边的子数组来构建
递归从根节点开始到左右子树构建子树,最后返回构建完成的根节点。
Java解法(递归,深度优先遍历):
class Solution {public int findMaxIndex(int[] nums){int res = -1, max = -1;for(int i = 0; i < nums.length; i++){if(max < nums[i]){max = nums[i];res = i;}}return res;}public TreeNode constructMaximumBinaryTree(int[] nums) {if(nums.length == 0)return null;if(nums.length == 1)return new TreeNode(nums[0]);int max_i = this.findMaxIndex(nums);TreeNode root = new TreeNode(nums[max_i]);root.left = this.constructMaximumBinaryTree(Arrays.copyOfRange(nums, 0, max_i));root.right = this.constructMaximumBinaryTree(Arrays.copyOfRange(nums, max_i+1, nums.length));return root;}
}
合并二叉树
题目详细:LeetCode.617
通过合并二叉树的过程,不难发现,在合并过程中会出现这4种情况(这里将要合并的树记作 root1 和 root2,让root2合并到root1):
- root1 != null && root2 != null,那么两个节点的值相加,root1.val += root2.val;
- root1 == null && root2 != null,左节点为空,那么直接将 root2 合并到 root1 中;
- root1 != null && root2 == null,右节点为空,那么无需合并,直接返回左节点
- root1 == null && root2 == null,左右节点都为空,无需合并或二叉树已完成合并
递归从根节点到左右子树开始合并子树,最后返回合并完成的根节点(root1)。
Java解法(递归,深度优先遍历):
class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {if(root1 == null){// root1 != null && root2 != nullreturn root2;}else if(root2 == null){// root1 == null && root2 != nullreturn root1;}// root1 != null && root2 == nullroot1.val += root2.val;root1.left = mergeTrees(root1.left, root2.left);root1.right = mergeTrees(root1.right, root2.right);return root1;}
}
二叉搜索树中的搜索
题目详细:LeetCode.700
二叉搜索树的特点可以简要概括为:
- 从根节点开始构建一棵二叉树,使其每一棵子树都满足
- 左节点的值 < 父节点的值
- 右节点的值 > 父节点的值
- 【注意】所以一棵真正的二叉搜索树应满足:
- 左子树上
所有的
节点值都 < 父节点的值 - 右子树上
所有的
节点值都 > 父节点的值
- 左子树上
- 那么我们则称这棵树为二叉搜索树
那么这道题要求在二叉搜索树中找到目标值对应的子树,利用二叉搜索树的特点和递归来解题就非常清晰易懂了,在搜索过程中会遇到这3种情况:
- 节点为空,则二叉树中不到目标值节点,返回null
- 节点的值 > 目标值,说明目标值只可能在二叉搜索树的右子树出现,递归搜索右子树
- 节点的值 < 目标值,说明目标值只可能在二叉搜索树的左子树出现,递归搜索左子树
- 节点的值 = 目标值,说明当前节点就是我们要找的子树的根节点,返回该节点
Java解法(递归,深度优先遍历):
class Solution {public TreeNode searchBST(TreeNode root, int val) {if(null == root) return null;if(val < root.val){return searchBST(root.left, val);}else if(val > root.val){return searchBST(root.right, val);}// val == root.valreturn root;}
}
验证二叉搜索树
题目详细:LeetCode.98
Java(错误的解法,陷进了一个大坑):
class Solution {public boolean isValidBST(TreeNode root) {return this.dfs(root.left, root.val, true) && this.dfs(root.right, root.val, false);}public boolean dfs(TreeNode root, int father_val, boolean is_left){if(root == null) return true;boolean flag = false;if(is_left){flag = root.val < father_val}else{flag = root.val > father_val}return flag && this.dfs(root.left, root.val, true) && this.dfs(root.right, root.val, false);}
}
一开始我发现这道题很简单,不就是根据二叉搜索树的特点来验证一棵二叉树是不是搜索树么,然后就得出结论:
- 递归验证每一个树的节点是否满足二叉搜索树的特点
- 二叉搜索树的特点在上一题有讲述,这里就不做赘述了
- 如果每一个节点都满足,那么则视作整体满足,返回 true
接着写完我就非常自信地提交了答案!很好,错误的测试例子出现了:
验证了一下算法,发现到达节点值为3的节点时,应该返回 false,因为假如构建一棵二叉搜索树的话,节点3应该是节点4的左节点才对。
所以:
- 不能单纯地对每一个节点判断其是否满足左节点 < 父节点,右节点 > 父节点就完事了。
- 一棵真正的二叉搜索树还需要满足的条件是
左子树所有节点 < 父节点,右子树所有节点 > 父节点
。
从二叉搜索树的特点,还可以发现其中序遍历序列,是一个递增序列,那么解题方法忽如一夜春风来,千树万树梨花开呀:
- 解法一:
- 我们可以直接对该二叉树进行中序遍历,获取该树的中序遍历序列;
- 判断该遍历序列是否是递增的,如果是递增序列,则说明该树是二叉搜索树,否则不是。
Java解法(中序遍历,验证二叉搜索树的中序遍历序列是否是递增序列):
class Solution {List<Integer> inorder_list = new ArrayList<>();public void dfs(TreeNode root){if(root == null) return;dfs(root.left);inorder_list.add(root.val);dfs(root.right);}public boolean isValidBST(TreeNode root) {this.dfs(root);int pre = Integer.MIN_VALUE;for(int i: this.inorder_list){if(pre > i) return false;pre = i;}return true;}
}
- 解法二:
- 从解法一可知,我们可以通过验证中序遍历序列是否递增,进而判断该树是否为二叉搜索树
- 那么我们也可以模拟这一思想,改用迭代的算法能够一边遍历节点,一边处理节点
- 一边迭代遍历二叉树,一边比较与前一个遍历的值,来判断遍历序列是否有序,进而判断该树是否为二叉树
Java解法(中序遍历,模拟,迭代,一边遍历一边比较):
class Solution {public boolean inorder(TreeNode root){Stack<TreeNode> stack = new Stack<>();if(null != root) stack.push(root);TreeNode pre = null;while(!stack.isEmpty()){TreeNode node = stack.pop();if(null != node){// 以右根左的顺序进栈,出栈顺序为左根右if(null != node.right) stack.push(node.right);stack.push(node);stack.push(null);if(null != node.left) stack.push(node.left);}else{node = stack.pop();if(null != pre && node.val <= pre.val) return false;pre = node;}}return true;}public boolean isValidBST(TreeNode root) {return this.inorder(root);}
}
天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。
天下的事情有困难和容易的区别吗?只要肯做,那么困难的事情也变得容易了;如果不做,那么容易的事情也变得困难了。人们做学问有困难和容易的区别吗?只要肯学,那么困难的学问也变得容易了;如果不学,那么容易的学问也变得困难了。
这首诗出自清代彭端淑的《为学一首示子侄》,最近我一直在努力学习,但又一直感觉自己为面试的准备工作很不充分,不敢大胆投简历,也不敢去面试,看完这首诗之后,恍然大悟:
“世上无难事,只怕有心人。”,亦是同样的道理,困难是可以克服的,慢慢来吧。
相关文章:

【代码随想录训练营】【Day19休息】【Day20】第六章|二叉树|654.最大二叉树|617.合并二叉树|700.二叉搜索树中的搜索|98.验证二叉搜索树
最大二叉树 题目详细:LeetCode.654 这道题在题目几乎就说明了解题的思路了: 创建一个根节点,其值为 nums 中的最大值;递归地在最大值左边的子数组上构建左子树;递归地在最大值右边的子数组上构建右子树;…...

华为云计算之容灾技术
容灾是物理上的容错技术,不是逻辑上的容错同步远程复制:主备距离≤200km,只有在主备设备上都写成功,才会告诉主机写成功,不会丢失数据异步远程复制:主备距离>200km,只要主设备上写成…...

React系列之Redux
1 Redux概述 Redux 是 JavaScript 状态容器,提供可预测化的状态管理。Redux中文文档 Redux 和react没有必然关系,redux可以应用于各种框架,包括jquery,甚至js都可以使用redux,只不过redux和react更加搭配。redux也推…...

最简单得方法解决TCP分包粘包问题
如何用最简单的方法解决TCP传输中的分包粘包问题? 首先需要说明一点,分包粘包等等一系列的问题并不是协议本身存在的问题,而是程序员在写代码的时候,没有搞清楚数据的边界导致的。 看个简单的例子,TCP客户端不断的向服…...

免费使用通配符域名证书
文章目录前言一、手动安装acme.sh操作1、安装acme.sh2、使用dns api自动续签二、宝塔自动操作【推荐】总结前言 之前个人站点一般都是使用阿里云免费单域名证书,虽然好用但是只有一年有效,到期只能手动重新申请,并且每次弄个子域名出来就要重…...

0基础成功转行Python自动化测试工程师,年薪30W+,经验总结都在这(建议收藏)
两年前的决定我觉得还是非常正确的,就是自学了python,然后学习了自动化测试、性能测试、框架、持续集成,同时也把前面的软件测试基础知识全部补全了。目前的收入还比较满意,月入2W(仅代表个人收入),13薪&am…...

MyBaits
MyBaitsMyBaits的jar包介绍MyBaits的入门案例创建实体java日志处理框架常用的日志处理框架Log4j的日志级别Mybatis配置的完善Mybatis的日志管理使用别名alias方式一方式二SqlSession对象下的常用API查询操作Mapper动态代理Mapper 动态代理规范查询所有用户根据用户ID查询用户Ma…...

kubeadm的部署、Dashboard UI以及连接私有仓库
目录 一、kubeadm 部署 K8S 集群架构 1、环境准备 2、所有节点安装docker 3、所有节点安装kubeadm,kubelet和kubectl 3、部署K8S集群 二、dashboard 部署 1、 安装dashboard 2、使用火狐或者360浏览器访问 三 、安装Harbor私有仓库 四、 内核参数优化方案 …...
刷题记录:牛客NC20325[SDOI2009]HH的项链
传送门:牛客 题目描述: HH有一串由各种漂亮的贝壳组成的项链。 HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一 段贝壳,思考它们所表达的含义。 HH不断地收集新的贝壳,因此他的项链变得越来越长。 有一天&#…...
【REACT-路由v6】
REACT-路由v61. App.js2. 搭建路由2.1 普通写法2.2 使用useRoutes构建路由2.3 重定向封装2.4 嵌套路由中的组件Outlet3. 导航跳转3.2 声明式导航(NavLink标签)3.2 编程式导航跳转(useNavigate)3.2.1 获取参数3.2.1.1 useSearchPar…...

【离散数学】3. 代数系统
1.数理逻辑 2. 集合论 3. 代数系统 4. 图论 代数系统:把一些形式上很不相同的代数系统,用统一的方法描述、研究、推理,从而得到反映出他们共性的一些结论,在将结论运用到具体的代数系统中 系统:运算研究对象 运算&…...

深度学习常用的优化器整理
常见优化器整理 一、SGD(随机梯度下降) 公式: 经典的mini-batch SGD使用的很多,效果也比较不错,但是存在一部分问题 选择恰当的初始学习率很困难学习率调整策略受限于预先制定的调整规则相同的学习率被应用于各个参数…...

Java 内部类
文章目录1、初识内部类2、非静态内部类(实例内部类)3、静态内部类(重点)4、内部类的使用5、局部内部类6、匿名内部类1、初识内部类 如果一个事物的内部包含另一个事物,那么这是一个类的内部包含另一个类。 例如&…...

【FAQ】集成分析服务的常见问题及解决方案
常见问题一:如何验证Analytics是否上报/接入成功?以及关键日志含义是什么? 在初始化Analytics SDK前添加SDK日志开关如下: HiAnalyticsTools.enableLog (); 2.初始化SDK代码如下: HiAnalyticsInstance instance Hi…...

11.注意力机制
11.注意力机制 目录 注意力提示 查询、键和值 注意力的可视化 注意力汇聚:Nadaraya-Watson 核回归 生成数据集 非参注意力池化层 Nadaraya-Watson核回归 参数化的注意力机制 批量矩阵乘法 定义模型 训练 注意力评分函数 掩蔽softmax操作 加性注意力 缩…...

45岁当打之年再创业,剑指中国版ChatGPT,这位美团联合创始人能否圆梦?
文 BFT机器人 “即便只有一个人,我也要出发。” 这是45岁的前美团联合创始人王慧文再次冲上创业沙场的“征战”宣言,这一次他的梦想是“组队拥抱新时代,打造中国OpenAI”。 01 当打之年, AI新梦再起航 “我的人工智能宣言&…...
数据结构——第二章 线性表(2)——链式存储结构
链式存储结构1 线性表的链式存储结构1.1不带头结点的单向链表1.2 带头结点的单向链表2 单向链表的基本操作实现2.1 单向链表的初始化操作2.2 单向链表的插入操作2.3. 单链表的删除操作2.4.单向链表的更新操作2.5.单向链表的求长度操作2.6.单向链表的定位操作2.7.单向链表的遍历…...
【更新】囚生CYの备忘录(20230216~)
序言 阳历生日。今年因为年过得早的缘故,很多事情都相对提前了(比如情人节)。往年过生日的时候基本都还在家,所以一家子出去吃个饭也就罢了。今年承蒙凯爹厚爱,正好也有小半年没聚,他前天也刚正式拿到offe…...

分布式事务几种方案
1)、2PC 模式 数据库支持的 2PC【2 phase commit 二阶提交】,又叫做 XA Transactions。 MySQL 从 5.5 版本开始支持,SQL Server 2005 开始支持,Oracle 7 开始支持。 其中,XA 是一个两阶段提交协议,该协议…...

Eclipse各版本安装Tomcat插件全攻略
Eclipse Tomcat 插件的作用 Eclipse Tomcat 插件可以将Tomcat 集成到Eclipse中,插件安装之后在Eclipse中可以看到类似下面的几个图标: Eclipse Tomcat 插件的主要作用有: 在Eclipse 中可以直接启动,关闭和重启本机的Tomcat可以…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...