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

【代码随想录训练营】【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.验证二叉搜索树

最大二叉树 题目详细&#xff1a;LeetCode.654 这道题在题目几乎就说明了解题的思路了&#xff1a; 创建一个根节点&#xff0c;其值为 nums 中的最大值&#xff1b;递归地在最大值左边的子数组上构建左子树&#xff1b;递归地在最大值右边的子数组上构建右子树&#xff1b;…...

华为云计算之容灾技术

容灾是物理上的容错技术&#xff0c;不是逻辑上的容错同步远程复制&#xff1a;主备距离≤200km&#xff0c;只有在主备设备上都写成功&#xff0c;才会告诉主机写成功&#xff0c;不会丢失数据异步远程复制&#xff1a;主备距离&#xff1e;200km&#xff0c;只要主设备上写成…...

React系列之Redux

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

最简单得方法解决TCP分包粘包问题

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

免费使用通配符域名证书

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

0基础成功转行Python自动化测试工程师,年薪30W+,经验总结都在这(建议收藏)

两年前的决定我觉得还是非常正确的&#xff0c;就是自学了python&#xff0c;然后学习了自动化测试、性能测试、框架、持续集成&#xff0c;同时也把前面的软件测试基础知识全部补全了。目前的收入还比较满意&#xff0c;月入2W&#xff08;仅代表个人收入&#xff09;,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&#xff0c;kubelet和kubectl 3、部署K8S集群 二、dashboard 部署 1、 安装dashboard 2、使用火狐或者360浏览器访问 三 、安装Harbor私有仓库 四、 内核参数优化方案 …...

刷题记录:牛客NC20325[SDOI2009]HH的项链

传送门:牛客 题目描述: HH有一串由各种漂亮的贝壳组成的项链。 HH相信不同的贝壳会带来好运&#xff0c;所以每次散步完后&#xff0c;他都会随意取出一 段贝壳&#xff0c;思考它们所表达的含义。 HH不断地收集新的贝壳&#xff0c;因此他的项链变得越来越长。 有一天&#…...

【REACT-路由v6】

REACT-路由v61. App.js2. 搭建路由2.1 普通写法2.2 使用useRoutes构建路由2.3 重定向封装2.4 嵌套路由中的组件Outlet3. 导航跳转3.2 声明式导航&#xff08;NavLink标签&#xff09;3.2 编程式导航跳转&#xff08;useNavigate&#xff09;3.2.1 获取参数3.2.1.1 useSearchPar…...

【离散数学】3. 代数系统

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

深度学习常用的优化器整理

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

Java 内部类

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

【FAQ】集成分析服务的常见问题及解决方案

常见问题一&#xff1a;如何验证Analytics是否上报/接入成功&#xff1f;以及关键日志含义是什么&#xff1f; 在初始化Analytics SDK前添加SDK日志开关如下&#xff1a; HiAnalyticsTools.enableLog (); 2.初始化SDK代码如下&#xff1a; HiAnalyticsInstance instance Hi…...

11.注意力机制

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

45岁当打之年再创业,剑指中国版ChatGPT,这位美团联合创始人能否圆梦?

文 BFT机器人 “即便只有一个人&#xff0c;我也要出发。” 这是45岁的前美团联合创始人王慧文再次冲上创业沙场的“征战”宣言&#xff0c;这一次他的梦想是“组队拥抱新时代&#xff0c;打造中国OpenAI”。 01 当打之年&#xff0c; AI新梦再起航 “我的人工智能宣言&…...

数据结构——第二章 线性表(2)——链式存储结构

链式存储结构1 线性表的链式存储结构1.1不带头结点的单向链表1.2 带头结点的单向链表2 单向链表的基本操作实现2.1 单向链表的初始化操作2.2 单向链表的插入操作2.3. 单链表的删除操作2.4.单向链表的更新操作2.5.单向链表的求长度操作2.6.单向链表的定位操作2.7.单向链表的遍历…...

【更新】囚生CYの备忘录(20230216~)

序言 阳历生日。今年因为年过得早的缘故&#xff0c;很多事情都相对提前了&#xff08;比如情人节&#xff09;。往年过生日的时候基本都还在家&#xff0c;所以一家子出去吃个饭也就罢了。今年承蒙凯爹厚爱&#xff0c;正好也有小半年没聚&#xff0c;他前天也刚正式拿到offe…...

分布式事务几种方案

1&#xff09;、2PC 模式 数据库支持的 2PC【2 phase commit 二阶提交】&#xff0c;又叫做 XA Transactions。 MySQL 从 5.5 版本开始支持&#xff0c;SQL Server 2005 开始支持&#xff0c;Oracle 7 开始支持。 其中&#xff0c;XA 是一个两阶段提交协议&#xff0c;该协议…...

Eclipse各版本安装Tomcat插件全攻略

Eclipse Tomcat 插件的作用 Eclipse Tomcat 插件可以将Tomcat 集成到Eclipse中&#xff0c;插件安装之后在Eclipse中可以看到类似下面的几个图标&#xff1a; Eclipse Tomcat 插件的主要作用有&#xff1a; 在Eclipse 中可以直接启动&#xff0c;关闭和重启本机的Tomcat可以…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...