算法学习笔记(五):二叉树一遍历、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:主键顺…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...