代码随想录第十四天|二叉树part02--226.翻转二叉树、101.对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度
资料引用:
226.翻转二叉树(226.翻转二叉树)
101.对称二叉树(101.对称二叉树)
104.二叉树的最大深度(104.二叉树的最大深度)
111.二叉树的最小深度(111.二叉树的最小深度)
226.翻转二叉树(226.翻转二叉树)
题目分析:
给定一棵二叉树的根节点root,翻转二叉树,使每一棵子树的根节点的左右孩子交换,最后返回根节点。
解题重点:
选择合适的遍历方式以便于处理。
解题思路:
考虑采取递归的遍历方式进行处理,使用前序或后序遍历皆可。
- 递归函数的参数:待处理的子树根节点
- 递归函数的返回值:处理完毕的子树根节点
- 递归函数的终止条件:遇到空节点直接返回
- 递归函数的单层递归逻辑:
-
- 前序遍历:终止条件判断、swap左右孩子,递归进入左孩子,递归进入右孩子,返回当前根节点
- 后序遍历:终止条件判断、递归进入左孩子,递归进入右孩子,swap左右孩子,返回当前根节点
注意:
为什么不使用中序遍历?
因为中序遍历是左中右,先完成对左子树的翻转,再将左右子树互换,此时若再对当前的右子树做翻转,实际上是对互换前的、已经完成翻转的“前左子树”做翻转。
修改方式:左中“左”
总结反思:
需要把握好不同遍历方式下处理操作的顺序,尤其是前(后)序和中序之间的区别。
class Solution {public TreeNode invertTree(TreeNode root) {if (root == null) return root;swap_Kids(root);invertTree(root.left);invertTree(root.right);return root;}public void swap_Kids (TreeNode root) {TreeNode tmpNode = root.left;root.left = root.right;root.right = tmpNode;return;}
}
101.对称二叉树(101.对称二叉树)
题目分析:
给定一个二叉树的根节点root,判断其是否为轴对称的,即翻转后树的节点值是否不变(包括空值)。
解题重点:
选择合适的遍历方式,方便比较。
简单思路:
先遍历取节点值,包括空值,用StringBuilder存储(便于存储空值),
再翻转二叉树,
最后用相同的方式遍历取节点值,实时比较是否与第一步得到的字符数组相同。
此处采取前序遍历。
class Solution {public boolean isSymmetric(TreeNode root) {if (root == null) return true;StringBuilder sb1 = new StringBuilder();StringBuilder sb2 = new StringBuilder();preOrder(root, sb1);invertTree(root);preOrder(root, sb2);return sb1.toString().equals(sb2.toString());}public void preOrder(TreeNode root, StringBuilder sb){if(root == null) {sb.append("\0");return;}sb.append(Integer.toString(root.val));preOrder(root.left, sb);preOrder(root.right, sb);}public TreeNode invertTree(TreeNode root) {if (root == null) return root;swap_Kids(root);invertTree(root.left);invertTree(root.right);return root;}public void swap_Kids (TreeNode root) {TreeNode tmpNode = root.left;root.left = root.right;root.right = tmpNode;return;}
}
推荐思路:
比较的不是二叉树的左右节点,比较的是根节点的左子树和右子树是不是相互翻转的,即比较对象是左右子树。
因此,在递归遍历过程中,要同时遍历两棵树。
由翻转的特性,我们定义:靠近中轴的是里侧节点,远离中轴的外侧节点。
选择“后序遍历”:通过递归函数的返回值判断两个子树之间的内侧节点和外侧节点是否相等。
准确来说:对两个子树的遍历应当分别为左右中和右左中。
定义递归比较函数compare如下:
-
- 递归函数的参数:左右子树节点
- 递归函数的返回值:布尔值
- 确定终止条件:
-
-
- 节点为空的情况:
-
-
-
-
- 左空,右非空,return false
- 左非空,右空,return false
- 左右都为空,对称,return true
-
-
-
-
- 节点非空的情况:
-
-
-
-
- 左右都非空,节点值不同false,相同继续
-
-
-
- 递归函数的单层递归逻辑:处理 左右节点都不为空,且数值相同的情况
-
-
- 递归比较左孩子的左孩子 和 右孩子的右孩子(外侧节点)
- 递归比较左孩子的右孩子 和 右孩子的左孩子(里侧节点)
- 取前两者的逻辑并,返回该值。
-
class Solution {public boolean isSymmetric(TreeNode root) {if (root == null) return true;return compareLR(root.left, root.right);}public boolean compareLR(TreeNode left, TreeNode right) {// 首先排除节点为空的情况if (left == null && right != null) return false;else if (left != null && right == null) return false;else if (left == null && right == null) return true;// 然后排除节点不为空时,两节点值不相等的情况else if (left.val != right.val) return false;// 递归比较外侧节点和里侧节点,取逻辑并boolean outside = compareLR(left.left, right.right);boolean inside = compareLR(left.right, right.left);boolean isSame = outside && inside;return isSame;}
}
总结反思:
学会根据任务需求灵活调整遍历方式进行比较。
递归中的三要素需要在掌握的基础上根据实际情况来调整完善,尤其是终止条件的合理设定,非常重要。
104.二叉树的最大深度(104.二叉树的最大深度)
题目分析:
给定一个二叉树,返回其最大深度。
解题重点:
对于一个二叉树,求其最大深度,则在递归遍历过程中增加deep参数的传递。
注意:
最大深度定义为:从根节点到最远叶子节点的最长路径上的节点数,因此最小深度从1开始(根节点不为空,若为空返回0)。
解题思路:
构造递归函数getMaxDepth如下:
- 递归函数的参数:节点node,当前深度deep
- 递归函数的返回值:最终深度deep,整型
- 递归函数的终止条件:遇到空节点,返回当前deep
- 递归函数的单层递归逻辑:节点为空,返回deep。节点不为空,deep++,递归查询左子树的最大深度left_depth和右子树的最大深度right_depth,取较大者返回。
总结:
注意通过递归函数的参数传递,实现当前深度deep的记录,并注意比较左右子树取较大者。
class Solution {public int maxDepth(TreeNode root) {return getMaxDepth(root, 0);}public int getMaxDepth(TreeNode root, int deep) {if (root == null) return deep;deep++;int left_depth = getMaxDepth(root.left, deep);int right_depth = getMaxDepth(root.right, deep);return left_depth > right_depth ? left_depth : right_depth;}
}
111.二叉树的最小深度(111.二叉树的最小深度)
题目分析:
给定一个二叉树的根节点root,找出其最小深度。
注意:
最小深度的定义:从根节点到最近叶子结点的最短路径上的节点数。
解题重点:
需要排除左(右)子树为空的这条路径
解题思路与优化:
后序遍历:
- 自底向上求高度(等价于求深度),
- 终止条件是遇到空节点时返回0(叶子节点为从1开始)
- 通过递归的逐级返回进行自增即可
- 注意排除节点为空的情况,不可作为最小深度比较对象
前序遍历:
- 自顶向下求深度
- 终止条件是遇到空节点时不自增,直接返回当前积累深度deep
- 通过递归返回的是最底层的计算结果,是通过逐级向下递归时自增的
- 需要额外增加参数--当前深度deep,因此需要构造新的递归函数
- 相较后序并不简洁,但也可实现。
层序遍历(迭代法):
- 层序遍历通过队列实现
- 需要注意的是:只有当左右孩子都为空,才说明是抵达叶子节点,否则继续
- 首次抵达叶子结点时,由于层序遍历是从上往下遍历,所以正是最近叶子节点
总结反思:
理解前序遍历和后序遍历的“方向”区别,根据实际情景选取适合的遍历方式。
理解题意很重要,不要经验主义下判断~
/*后序遍历 递归法*/
class Solution {/*该解法实际是后序遍历,相当于求最小高度,等价于求最小深度 */public int minDepth(TreeNode root) {if (root == null) return 0;int leftDepth = minDepth(root.left);int rightDepth = minDepth(root.right);if (root.left == null) return rightDepth+1;if (root.right == null) return leftDepth+1;return leftDepth < rightDepth ? leftDepth+1 : rightDepth+1;}
}
/*前序遍历 递归法*/
class Solution {public int minDepth(TreeNode root) {return getMinDepth(root, 0);}public int getMinDepth(TreeNode root, int deep) {if (root == null) return deep;deep++;int left_depth = 0;int right_depth = 0;if (root.left == null) return getMinDepth(root.right, deep);else if (root.right == null) return getMinDepth(root.left, deep);left_depth = getMinDepth(root.left, deep);right_depth = getMinDepth(root.right, deep);return left_depth < right_depth ? left_depth : right_depth;}
}
/*层序遍历 迭代法*/
class Solution {public int minDepth(TreeNode root) {if (root == null) {return 0;}Deque<TreeNode> deque = new ArrayDeque<>();deque.offer(root);int depth = 0;while (!deque.isEmpty()) {int size = deque.size();depth++;for (int i = 0; i < size; i++) {TreeNode poll = deque.poll();if (poll.left == null && poll.right == null) {// 因为从上往下遍历,所以是最近叶子结点,该值就是最小值,直接返回depthreturn depth;}if (poll.left != null) {deque.offer(poll.left);}if (poll.right != null) {deque.offer(poll.right);}}}return depth;}
}
相关文章:
代码随想录第十四天|二叉树part02--226.翻转二叉树、101.对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度
资料引用: 226.翻转二叉树(226.翻转二叉树) 101.对称二叉树(101.对称二叉树) 104.二叉树的最大深度(104.二叉树的最大深度) 111.二叉树的最小深度(111.二叉树的最小深度)…...
vue基础之7:天气案例、监视属性、深度监视、监视属性(简写)
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
JS实现高效导航——A*寻路算法+导航图简化法
一、如何实现两点间路径导航 导航实现的通用步骤,一般是: 1、网格划分 将地图划分为网格,即例如地图是一张图片,其像素为1000*1000,那我们将此图片划分为各个10*10的网格,从而提高寻路算法的计算量。 2、标…...
Spring Authorization Server登出说明与实践
本章内容概览 Spring Security提供的/logout登出接口做了什么与如何自定义。Spring Authorization Server提供的/connect/logout登出接口做了什么与如何自定义。Spring Authorization Server提供的/oauth2/revoke撤销token接口做了什么与如何自定义。 前言 既然系统中有登录功…...
浏览器报错 | 代理服务器可能有问题,或地址不正确
1 问题描述 Windows连网情况下,浏览器访问地址显示“你尚未连接,代理服务器可能有问题,或地址不正确。”出现如下画面: 2 解决方法 途径1 控制面板-->网络与internet-->internet选项-->Internet属性-->连接-->…...
泷羽sec:shell编程(9)不同脚本的互相调用和重定向操作
声明: 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…...
Milvus×OPPO:如何构建更懂你的大模型助手
01. 背景 AI业务快速增长下传统关系型数据库无法满足需求。 2024年恰逢OPPO品牌20周年,OPPO也宣布正式进入AI手机的时代。超千万用户开始通过例如通话摘要、新小布助手、小布照相馆等搭载在OPPO手机上的应用体验AI能力。 与传统的应用不同的是,在AI驱动的…...
单片机几大时钟源
在单片机中,MSI、HSI和HSE通常指的是用于内部晶振配置的不同功能模块: MSI (Master Oscillator System Interface):这是最低级的一种时钟源管理单元,它控制着最基本的系统时钟(SYSCLK),一般由外…...
reverse学习总结(12)
一.[FlareOn4]IgniteMe1 https://files.buuoj.cn/files/02b39b8efca02367af23aa279c81cbec/attachment.zip 根据汇编语言分析 查看需要返回为1的函数 int sub_401050() {int v1; // [esp0h] [ebp-Ch]int i; // [esp4h] [ebp-8h]unsigned int j; // [esp4h] [ebp-8h]char v4; …...
基于“微店 Park”模式下 2+1 链动模式商城小程序的创新发展与应用研究
摘要:本文以“微店 Park”从“开店工具”向“众创平台”的转型为背景,深入探讨 21 链动模式商城小程序在该平台情境下的应用潜力与创新发展路径。通过剖析“微店 Park”的运营模式,包括灵活承租、低成本入驻、多元流量引流等特点,…...
C++11:【列表初始化】【右值引用和移动语义】
目录 一.列表初始化 1.1 C98传统的{} 1.2C11中的{} 1.3C中的std::initializer_list 二.右值引用和移动语义 2.1左值和右值 2.2左值引用和右值引用 2.3引用延长生命周期 2.4左值和右值的参数匹配 2.5右值引用和移动语义的使用场景 2.5.1左值引用主要使用场景 2.5.2移…...
Zookeeper的通知机制是什么?
大家好,我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper的通知机制主要通过Watcher实现,它是Zookeeper客…...
嵌入式蓝桥杯学习1 电量LED
cubemx配置 1.新建一个STM32G431RBT6文件 2.在System-Core中点击SYS,找到Debug(设置为Serial Wire) 3.在System-Core中点击RCC,找到High Speed Clock(设置为Crystal/Ceramic Resonator) 4.打开Clock Configuration ࿰…...
bsmap输出结果解释
关于, , -, --的解释 对应着参考基因组的正链(有义链,非模板链,即hg38的序列,watson链); -代表正链的互补链(正常情况下正链的互补链是负链,但在重硫酸盐处理后正链和负链并不互补…...
【java-数据结构篇】揭秘 Java LinkedList:链表数据结构的 Java 实现原理与核心概念
我的个人主页 我的专栏:Java-数据结构,希望能帮助到大家!!!点赞❤ 收藏❤ 目录 1. Java LinkedList 基础 1.1 LinkedList 简介 1.2 LinkedList 的实现原理 1.3 LinkedList 与 ArrayList 的区别 2. 链表基础 2.1 链…...
macOS运行amd64的镜像
在macOS上运行amd64(x86_64)架构的镜像,通常通过虚拟化或仿真工具来实现。例如,如果你使用的是基于Apple Silicon(M1或M2等)芯片的Mac,那么你的处理器是ARM架构的,而amd64是x86架构&…...
轻量的基于图结构的RAG方案LightRAG
LightRAG出自2024年10月的论文《LIGHTRAG: SIMPLE AND FASTRETRIEVAL-AUGMENTED GENERATION》(github),也是使用图结构来索引和搜索相关文本。 LightRAG作者认为已有的RAG系统有如下两个限制,导致难以回答类似"How does the rise of electric vehi…...
计算机的错误计算(一百七十三)
摘要 给定多项式 在 MATLAB 中计算 的值。输出是错误结果。 例1. 已知 计算 直接贴图吧: 这样,MATLAB 输出了错误结果。因为准确值为 0.2401e-16 . 注:可参看计算机的错误计算(六)。...
【力扣】—— 二叉树的前序遍历、字典序最小回文串
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:数据结构 📚本系列文章为个人学…...
linux替换更高版本gcc
实际使用时对与gcc版本有很多要求, 需要在centos上安装更高版本的gcc 1、安装centos-release-scl sudo yum install centos-release-scl2、安装devtoolset,注意,如果想安装7.版本的,就改成devtoolset-7-gcc,以此类推 sudo yum …...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
