算法学习笔记(五):二叉树一遍历、DFS
一.遍历二叉树
二叉树TreeNode类
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
前:NLR
中:LNR
后:LRN
二叉树遍历的本质是递归。
1.二叉树的前序遍历
给你二叉树的根节点 root,返回它节点值的 前序 遍历
class Solution {public List<Integer> preorderTraversal(TreeNode root) {//前序遍历就是NLR 先输出根节点 再输出左节点 再输出右节点//然后以此类推,每个节点都是这样的顺序 所以这是一个子问题//而整个二叉树可以由多个子问题解决 所以可以递归List<Integer> list = new ArrayList<>();dfs(root, list);return list;}private void dfs(TreeNode root, List<Integer> list) {if (root == null) return;list.add(root.val);dfs(root.left, list);dfs(root.right, list);}
}
2.二叉树的中序遍历
给定一个二叉树的根节点 root,返回它的中序遍历
class Solution {public List<Integer> inorderTraversal(TreeNode root) {//中序遍历 LNRList<Integer> list = new ArrayList<>();dfs(root, list);return list;}private void dfs(TreeNode root, List<Integer> list) {if (root == null) return;dfs(root.left, list);list.add(root.val);dfs(root.right, list);}
}
3.二叉树的后续遍历
给你一棵二叉树的根节点 root,返回它的 后续遍历
class Solution {public List<Integer> postorderTraversal(TreeNode root) {//后续遍历就是LRNList<Integer> list = new ArrayList<>();dfs(root, list);return list;}public void dfs(TreeNode root, List<Integer> list) {if (root == null) return;dfs(root.left, list);dfs(root.right, list);list.add(root.val);}
}
4.叶子相似的树
请考虑一棵二叉树上所有的叶子,这些叶子的值按照从左到右的顺序排列形成一个 叶值序列
举个例子,如图所示,给定一棵叶值序列为 [6, 7, 4, 9, 8] 的树

如果有两棵二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的
如果两棵树是叶相似,返回true,否则返回false
class Solution {public boolean leafSimilar(TreeNode root1, TreeNode root2) {/**按照题目,叶值是从左到右排列的所以先从左子树开始遍历,找到叶子节点保存下来*/StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); dfs(root1, sb1);dfs(root2, sb2);return sb1.toString().equals(sb2.toString());}private void dfs(TreeNode root, StringBuilder sb) {if (root == null) return;if (root.left == root.right) {//叶子节点 因为left right都是null//append(",")是防止比如上一个是7,下一个是14 //然后第二棵树上一个是71,下一个是4这种情况sb.append(root.val).append(",");return;}//从左到右开始遍历dfs(root.left, sb);dfs(root.right, sb);}
}
5.开幕式焰火
[力扣挑战赛]开幕式开始了,空中绽放了一棵二叉树形的举行焰火,给定一棵二叉树 root
代表焰火,节点值表示巨型焰火这一位置的颜色种类
请帮小扣计算巨型焰火有多少种不同的颜色。
示例:
输入:root = [1, 3, 2, 1, null, 2]
输出:3 ,有3种颜色,分别是颜色1,2,3
class Solution {public int numColor(TreeNode root) {/**这个就是纯遍历二叉树,然后判断每个节点的不同的值有多少个*/Set<Integer> set = new HashSet<>();dfs(root, set);return set.size();}private void dfs(TreeNode root, Set<Integer> set) {if (root == null) return;set.add(root.val);dfs(root.left, set);dfs(root.right, set);}
}
6.左叶子之和
给定二叉树的根节点 root,返回所有的左叶子之和
class Solution {public int sumOfLeftLeaves(TreeNode root) {//叶子节点就是没有左右子节点的节点//重点是如何判断是左叶子return dfs(root);}private int dfs(TreeNode root) {if (root == null) return 0;int sum = 0;//如果当前节点有左节点并且左节点是叶子节点if (root.left != null && isLeaf(root.left)) {//直接计算左叶子节点之和sum += root.left.val;}//继续递归计算左子树和右子树的左叶子节点之和sum += dfs(root.left);sum += dfs(root.right);return sum;}private boolean isLeaf(TreeNode root) {return root.left == root.right;}
}
二.自顶向下DFS
在 递 的过程中维护值
1.二叉树的最大深度
给定一个二叉树 root,返回其最大深度
二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数
示例:
class Solution {public int maxDepth(TreeNode root) {//二叉树的最大深度公式://max = Math.max(左子树深度,右子树深度) + 1//所以就是遍历左右子树的深度 然后+1(根节点)就是二叉树的最大深度//然后同理,每个节点的最大深度都是等于它的左右子数最大深度+1//这样就可以递归解决这个问题 每个节点的算法都是一致的if (root == null) return 0;int left = maxDepth(root.left);int right = maxDepth(root.right);return Math.max(left, right) + 1;}
}
2.二叉树的最小深度
给定一个二叉树,找出其最小深度
最小深度是从根节点到最近叶子节点的最短路径上的节点数量
class Solution {private int min = Integer.MAX_VALUE; //不考虑多线程问题public int minDepth(TreeNode root) {//最小深度 也就是说到达最短叶子节点的节点数//想一下 怎么做?//上来直接判断当前节点是否是叶子节点 是的话就直接返回//这样是不是就是最小的?//但是没办法判断跟其他的比呀//增加一个全局变量 用来记录是叶子节点的时候节点数 每次只要最小的//传入一个count,用来记录当前叶子节点到根节点这条路径的节点数dfs(root, 0);return root == null ? 0 : min;}private void dfs(TreeNode root, int count) {if (root == null) return;//不是null ++ 表示节点+1count++;//如果当前节点是叶子节点 那么就算是到头了//计算到当前这个叶子节点的路径的总结点数和其他的作比较 if (root.left == root.right) {min = Math.min(min, count);return;}//否则继续往下递归dfs(root.left, count);dfs(root.right, count);}
}
3.路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum,判断该树中是否存在根节点
到叶子节点的路径,这条路径上所有节点值相加等于目标 targetSum,
存在返回true,否则返回false
示例:

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {//还是遍历二叉树,然后每当遍历到一个叶子节点的时候,//计算一下到当前这个叶子节点的路径节点之和是否等于targetSum//然后一直递归遍历if (root == null) return false;//判断是否是叶子节点if (root.left == root.right) {return root.val == targetSum;} //只要左右子树中有一个存在那么就是存在return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);}
}
4.求根节点到叶子节点数字之和
给你一个二叉树的根节点 root,树中每个节点都存放有一个 0 到 9 之间的数字
每条从根节点到叶节点的路径都代表一个数字
例如,从根节点到叶节点的路径是 1 -> 2 -> 3 表示数字123
计算从根节点到叶节点生成的所有数字之和
class Solution {private int sum = 0;public int sumNumbers(TreeNode root) {//这题和求链表的十进制数字之和类似//所以公式是: int sum = sum * 10 + val//然后递归遍历每一个子树 然后返回sum即可//看来还是需要一个全局变量来存 不然每个//叶子节点的值没办法相加dfs(root, sum);return sum;}private void dfs(TreeNode root, int val) {if (root == null) return;int count = val * 10 + root.val;//如果当前是叶子节点就直接返回if (root.left == root.right) {sum += count;return;}//否则继续递归dfs(root.left, count);dfs(root.right, count);return;}
}
5.二叉树的右视图
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回
右侧所能看到的节点值。

class Solution {public List<Integer> rightSideView(TreeNode root) {/**想下这题怎么做右视图,首先肯定是先遍历右子树,如果存在右子节点,那么肯定先看到的是右节点其实就是几种情况1.当前节点的左右节点一样高 那么右视图看到的是肯定是右节点2.当前节点的右节点比左节点高,那么还是看到右节点3.当前节点的右节点比左节点低,那么右节点下面的左节点也能被看到所以总结出来,当一个子树的深度首次到达时,那么这个节点就在右视图中但是得要先递归遍历右子树,再递归左子树,保证右子树先到达(左右子树同样高的情况)*/List<Integer> list = new ArrayList<>();dfs(root, list, 0);return list;}private void dfs(TreeNode root, List<Integer> list, int dept) {if (root == null) return;//判断当前节点是否首次到达 如何判断//根据list size,如果list.size == dept 那么就证明首次遍历到当前深度if (list.size() == dept++) {list.add(root.val);}//然后继续按照从右到左的顺序递归dfs(root.right, list, dept);dfs(root.left, list, dept);}
}
6.统计二叉树中好节点的数目
给你一棵根为 root 的二叉树,请你返回二叉树中好节点的数目
好节点 定义为:从根到该节点所经过的节点中,没有任何节点的值大于该节点的值
示例:

class Solution {private int count = 0;public int goodNodes(TreeNode root) {/**其实就是递归树,然后每次把遍历过的节点的最大值作为参数传到下一次递归中去,和当前节点值进行判断 */dfs(root, Integer.MIN_VALUE); return count;}private void dfs(TreeNode root, int max) {if (root == null) return;if (root.val >= max) {count++;max = root.val;}dfs(root.left, max);dfs(root.right, max);}
}相关文章:
算法学习笔记(五):二叉树一遍历、DFS
一.遍历二叉树 二叉树TreeNode类 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, Tree…...
#Verilog HDL# Verilog中的generate用法集锦
生成块允许复制模块实例或有条件地实例化任何模块。它提供了基于Verilog参数构建设计的能力。当相同的操作或模块实例需要重复多次,或者当某些代码需要根据给定的Verilog参数有条件地包含时,这些语句特别方便。 生成块不能包含端口、参数、specparam声明或指定块。但是,允许…...
简述C++map容器
pair键值对 std::pair在很多关联容器(如std::map、std::multimap、std::set、std:multiset等)中被广泛应用。以std::map为例,std::map是一个键值对的容器,其中每个元素都是一个std::pair,键用于唯一标识元…...
Vue 学习随笔系列十七 -- 表格样式修改
表格样式修改 文章目录 表格样式修改一、表格背景颜色修改1、方法一2、方法二 二、多级表头颜色修改 一、表格背景颜色修改 1、方法一 表格外套一个 div ,修改div的背景色,并将表格背景色设置为透明 参考代码: <template><div cl…...
08 —— Webpack打包图片
【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件:发送一个单独的文件并导出URL地址 小于8KB的文件:导出一…...
01.Django快速入门
一、Django 快速入门 使用最新版本 Django4.2LTS 版本,3 年内不需要更换版本由浅入深讲解,浅显易懂课程大纲全面包含 Django 框架知识点,内容丰富全面细致知识点结合项目实战实现全栈项目应用 Django 官网(文档): https://docs.djangoproject.com/zh-h…...
【大数据学习 | Spark-Core】spark-shell开发
spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码,会在driver端进行解析,然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...
Modern Effective C++ Item 14 如果函数不抛出异常请使用noexcept
C11 noexcept关键字用于指定函数不会抛出异常,有助于提高程序的异常安全性,还能够使编译器生成更加高效的代码。 noexcept 是函数接口的一部分 函数是否声明为 noexcept 是接口设计的一部分,客户端代码可能会依赖这一点。如果一个函数被声明…...
cudatoolkit安装(nvcc -V错误版本解决)
CudaToolKit安装(nvcc) cudatoolkit 是 CUDA 开发工具包(CUDA Toolkit) 的核心部分,包含了一系列用于开发和运行 CUDA 应用程序的软件组件。nvcc 是 NVIDIA CUDA 编译器驱动,用于将 CUDA C/C 代码编译成可…...
DTO和VO的区别及使用场景详解
随着互联网的发展,前后端分离的开发模式越来越流行。在前后端数据交互过程中,为了保证数据的安全性和效率,通常会采用 DTO 和 VO 来封装数据。本篇博客将详细介绍 DTO 和 VO 的区别以及使用场景。 大家可能会有个疑问,既然DTO是展…...
百度在下一盘大棋
这两天世界互联网大会在乌镇又召开了。 我看到一条新闻,今年世界互联网大会乌镇峰会发布“2024 年度中国互联网企业创新发展十大典型案例”,百度文心智能体平台入选。 这个智能体平台我最近也有所关注,接下来我就来讲讲它。 百度在下一盘大棋…...
第十六届蓝桥杯模拟赛第二期题解—Java
第十六届蓝桥杯模拟赛/校赛第二期个人题解,有错误的地方欢迎各位大佬指正 问题一(填空题) 【问题描述】 如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。 请问, 2024 的最大的质因数是多少? …...
驱动开发笔记:关于3588GPIO
1.概要 2.内容 1.3588GPIO 关于RK3588的GPIO(General-Purpose Input/Output,通用输入输出引脚),以下是一些关键信息和操作指南: 一、GPIO基本概念 定义:GPIO是嵌入式系统中常见的通信接口,…...
【RK3588 Linux 5.x 内核编程】-内核线程与Mutex
内核线程与Mutex 文章目录 内核线程与Mutex1、Mutex介绍1.1 竞争条件1.2 Mutex特性2、Linux内核中的Mutex2.1 初始化Mutex2.1.1 静态方式初始化2.1.2 动态方式初始化2.2 互斥锁获取2.3 互斥锁释放3、Mutex使用示例4、驱动验证在前面的文章中,介绍了如何Linux内核中的线程,但是…...
【0342】分配并初始化 Proc Signal 共享内存 (1)
1. Proc Signal (procsignal)共享内存 Postgres内核在启动postmaster守护进程时候, 会通过函数 ProcSignalShmemInit() 去为 Proc Signal 分配并初始化指定大小的共享内存空间。整个调用链路如下。 (gdb) bt #0 ProcSignalShmemInit () at procsignal.c:118 #1 0x000000000…...
管家婆财贸ERP BR035.回款利润明细表
最低适用版本: 财贸系列 23.5 插件简要功能说明: 报表统计销售单/销售退货单/销售发票回款情况更多细节描述见下方详细文档插件操作视频: 进销存类定制插件--回款利润明细表 插件详细功能文档: 1. 应用中心增加报表【回款利润明细表】 a. b. 查询条件: ⅰ. 日期区间:…...
数据库MYSQL——表的设计
文章目录 前言三大范式:几种实体间的关系:一对一关系:一对多关系:多对多关系: 前言 之前的博客中我们讲解的是关于数据库的增删改查与约束的基本操作, 是在已经创建数据库,表之上的操作。 在实…...
netstat -tuln | grep 27017(显示所有监听状态的 TCP 和 UDP 端口,并且以数字形式显示地址和端口号)
文章目录 1. 确定占用端口的进程使用 lsof 命令使用 fuser 命令 2. 结束占用端口的进程3. 修改 MongoDB 配置文件4. 检查 MongoDB 日志文件5. 重新启动 MongoDB 服务6. 检查 MongoDB 服务状态总结 [rootlocalhost etc]# netstat -tuln | grep 27017 tcp 0 0 127.0.…...
非线性控制器设计原理
非线性控制器设计原理 非线性控制器设计旨在解决非线性系统的控制问题,克服传统线性控制器在处理非线性现象(如饱和、死区、耦合、时变性等)时的不足。其核心在于利用非线性数学工具和设计方法,使控制系统在非线性条件下具备良好…...
MySQL数据库6——SQL优化
一.SQL优化 1.插入优化 优化1:批量插入 insert into 表名 values(记录1),(记录2),……;优化2:手动提交事务 start transaction; insert into 表名 values(记录1),(记录2); insert into 表名 values(记录1),(记录2); …… commit;优化3:主键顺…...
毕业论文难写?2026年AI写作辅助平台排行榜权威发布,轻松定稿不是梦!
写论文效率低、熬夜赶稿、查重不过关?别慌!2026 年最新 AI 论文写作工具合集来了,覆盖选题、大纲、初稿、润色、降重、格式、文献引用全流程,帮你精准匹配最适合的学术助手,彻底告别论文内耗!🏆…...
3步掌握OBS多平台直播:obs-multi-rtmp从零到精通的完整攻略
3步掌握OBS多平台直播:obs-multi-rtmp从零到精通的完整攻略 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 你是否曾为同时向多个平台直播而烦恼?传统方法需要重…...
OneBlog权限系统实战:RBAC与Apache Shiro的完美结合
OneBlog权限系统实战:RBAC与Apache Shiro的完美结合 【免费下载链接】OneBlog :alien: OneBlog,一个简洁美观、功能强大并且自适应的Java博客 项目地址: https://gitcode.com/gh_mirrors/on/OneBlog OneBlog是一个简洁美观、功能强大并且自适应的…...
从红宝石到光纤:固体激光器家族里,谁才是工业加工界的‘六边形战士’?
从红宝石到光纤:固体激光器家族里,谁才是工业加工界的‘六边形战士’? 在金属切割车间里,激光束正以毫米级精度划过不锈钢板;精密电子产线上,纳米级激光打标机为电路板刻印追溯码;汽车焊接工段…...
用Python从零搭建GridWorld环境:手把手教你实现值迭代与策略迭代(附完整代码)
用Python从零搭建GridWorld环境:手把手教你实现值迭代与策略迭代(附完整代码)在强化学习领域,GridWorld就像编程界的"Hello World",是理解基础算法的最佳试验场。不同于理论推导的抽象,亲手构建一…...
如何在Blender中实现专业级MMD模型动画制作:5步完整解决方案
如何在Blender中实现专业级MMD模型动画制作:5步完整解决方案 【免费下载链接】blender_mmd_tools MMD Tools is a blender addon for importing/exporting Models and Motions of MikuMikuDance. 项目地址: https://gitcode.com/gh_mirrors/bl/blender_mmd_tools …...
UE材质进阶:拆解WAT世界对齐纹理原理,从‘井盖积雪’到‘墙体苔藓’的通用实现思路
UE材质进阶:WAT世界对齐纹理原理与多场景实战指南想象一下这样的场景:你的开放世界游戏中,一辆越野车驶过泥泞道路,轮胎上的泥渍会随着行驶距离逐渐积累,但无论车辆如何移动旋转,泥渍纹理始终与地面环境保持…...
【AI搜索引擎未来5年趋势白皮书】:20位顶尖AI架构师联合预测的7大不可逆变革
更多请点击: https://intelliparadigm.com 第一章:AI搜索引擎未来5年趋势总览 AI搜索引擎正从关键词匹配的“检索工具”加速演进为具备推理能力、上下文感知与主动服务意识的“智能认知中枢”。未来五年,其技术演进将围绕多模态理解、实时知…...
JMeter临界部分控制器:业务节奏建模与资源争用压测核心
1. 为什么“临界部分控制器”是压测中真正卡住团队的隐形瓶颈?在JMeter压测项目里,我见过太多团队把90%精力花在“怎么造出1000并发”上——线程组配好、HTTP请求写完、监听器一开,看着Active Threads曲线冲上峰值就以为大功告成。结果一进生…...
Codex入门19-数据库操作(解放双手:用自然语言写SQL、建表和数据迁移)
Codex入门19-数据库操作(解放双手:用自然语言写SQL、建表和数据迁移) 📌 文章简介:写 SQL 是后端开发的日常,但复杂的 JOIN、子查询、窗口函数总让人头疼。本文教你用 Codex CLI 实现:自然语言直接生成 CREATE TABLE、复杂 SQL 查询、数据库迁移脚本(Prisma/Knex/Alem…...
