二叉树BFS

前置知识

二叉树节点的定义

  • 二叉树是递归定义的
/*** Definition for a binary tree node.(LeetCode)*/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;}
}

广度优先遍历搜索 Breath First Search (BFS)

BFS

  • BFS通常需要使用一个队列来维护搜索过程。
  • 先进先出 First In First Out (FIFO)。

层序遍历 Level-order Traverse

  • 树的广度优先遍历亦可称为层序遍历。
  • 从上到下、从左到右访问树中的节点,每一层的节点都按顺序出现。
    层序遍历

多源BFS

单源BFS:从某一个点开始(一个起点)。
多源BFS:从多个点同时开始走(多个起点)。

二叉树结构

LeetCode 2236. 判断根结点是否等于子结点之和

  • 比较二叉树根节点的值val、左子树left和右子树right节点的值之和
class Solution {public boolean checkTree(TreeNode root) {if( root.val == root.left.val + root.right.val )return true;elsereturn false;}
}

二叉树的层序遍历

LeetCode 102. 二叉树的层序遍历

  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {// 遍历结果,注意题目输出格式List<List<Integer>> traverseResult  = new LinkedList<>();// 根节点为空的情况if ( root == null )return traverseResult;// BFS,使用队列Queue<TreeNode> queue = new LinkedList<>();// 前面判断了根节点为空,这里根节点入队列queue.add(root);// 借助队列层序遍历二叉树,直到所有节点出列while( !queue.isEmpty() ) {// 每层节点个数int levelCount = queue.size();// 该层每个节点值List<Integer> levelResult = new ArrayList<>();// 遍历该层节点for (int i=0; i<levelCount; i++) {// 队头节点出队列TreeNode node = queue.poll();// 出列节点值,加入List集合levelResult.add(node.val);// 左节点存在,入队if ( node.left != null ) {queue.add( node.left );}// 右节点存在,入队if ( node.right != null ) {queue.add( node.right );}}// 该层遍历结果traverseResult.add( levelResult );}return traverseResult;}
}

LeetCode 107. 二叉树的层序遍历 II

  • BFS层序遍历,在遍历完一层节点之后,将存储该层节点值的列表添加到结果列表的头部。
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<List<Integer>> levelOrderBottom(TreeNode root) {// 遍历结果,注意题目输出格式、自底向上List<List<Integer>> traverseResult = new LinkedList<>();// 根节点为空的情况if ( root == null )return traverseResult;// BFS,使用队列Queue<TreeNode> queue = new LinkedList<>();// 前面判断了根节点为空,这里根节点入队列queue.add(root);// 借助队列层序遍历二叉树,直到所有节点出列while( !queue.isEmpty() ) {// 每层节点个数int levelCount = queue.size();// 该层每个节点值List<Integer> levelResult = new ArrayList<>();// 遍历该层节点for ( int i=0; i<levelCount; i++ ) {// 队头节点出队列TreeNode node = queue.poll();// 出列节点值,加入List集合levelResult.add(node.val);// 左节点存在,入队if ( node.left != null )queue.add(node.left);// 右节点存在,入队if ( node.right != null )queue.add(node.right);}// 该层遍历结果,将存储该层节点值的列表添加到结果列表的头部。traverseResult.add(0,levelResult);}return traverseResult;}
}

LeetCode 103. 二叉树的锯齿形层序遍历

  • BFS层序遍历,利用双端队列交替顺序输出每层结果。
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<List<Integer>> zigzagLevelOrder(TreeNode root) {List<List<Integer>> traverseResult = new LinkedList<>();if ( root == null )return traverseResult;// BFS层序遍历,双端队列实现输出顺序交替Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);// true时从左往右,false时从右往左boolean flag = true;while( !queue.isEmpty() ) {int levelCount = queue.size();// 双端队列LinkedList<Integer> levelResult = new LinkedList<>();for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();// 从左往右,插入双端队列末尾if(flag)levelResult.offerLast(node.val);// 从右往左,插入双端队列头部elselevelResult.offerFirst(node.val);if ( node.left != null)queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}traverseResult.add(levelResult);// 每层遍历完,修改标记flag = !flag;}return traverseResult;}
}

LeetCode 637. 二叉树的层平均值

  • BFS,层平均值 = 每层节点值之和 / 每层节点数量
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<Double> averageOfLevels(TreeNode root) {List<Double> avgResult = new ArrayList<>();Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while( !queue.isEmpty() ) {int levelCount = queue.size();double levelSum = 0;for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();levelSum += node.val;if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}avgResult.add( levelSum / levelCount );}return avgResult;}
}

LeetCode 199. 二叉树的右视图

  • BFS,记录下每层的最后一个元素。
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<Integer> rightSideView(TreeNode root) {List<Integer> rightResult = new ArrayList<>();if ( root == null )return rightResult;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while ( !queue.isEmpty() ) {int levelCount = queue.size();for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();// 每层最右侧节点if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);if (i+1 == levelCount)rightResult.add(node.val);}}return rightResult;}
}

LeetCode 513. 找树左下角的值

  • BFS层序遍历,最后更新的值,是最后一层最左节点值。
  • 注意节点值的数据范围, − 2 31 < = N o d e . v a l < = 2 31 − 1 -2^{31} <= Node.val <= 2^{31} - 1 231<=Node.val<=2311
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public int findBottomLeftValue(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int bottomLeft = root.val;while ( !queue.isEmpty() ) {int levelCount = queue.size();for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();// 每层最左边节点的值if ( i == 0 )bottomLeft = node.val;if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}}// 层序遍历,bottomLeft是最后一层最左边节点的值return bottomLeft;}
}

LeetCode 515. 在每个树行中找最大值

  • BFS层序遍历,取每层全部节点中的最大值。
  • 注意节点值的数据范围, − 2 31 < = N o d e . v a l < = 2 31 − 1 -2^{31} <= Node.val <= 2^{31} - 1 231<=Node.val<=2311
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public List<Integer> largestValues(TreeNode root) {List<Integer> largestResult = new LinkedList<>();if ( root == null )return largestResult;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while ( !queue.isEmpty() ) {int levelCount = queue.size();int maxValue = Integer.MIN_VALUE;for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();if ( maxValue < node.val )maxValue = node.val;if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}largestResult.add(maxValue);}return largestResult;}
}

LeetCode 1161. 最大层内元素和

  • BFS层序遍历,累加每层元素之和,记录和最大的层号。
  • 注意节点值的数据范围, − 1 0 5 < = N o d e . v a l < = 1 0 5 -10^{5} <= Node.val <= 10^{5} 105<=Node.val<=105
  • 注意变量赋值位置,是否受循环影响(代码思路没错,卡在这个细节好久,最后发现是这里的问题)
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public int maxLevelSum(TreeNode root) {int maxLevel = 1;int maxSum = Integer.MIN_VALUE;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int level = 1;while ( !queue.isEmpty() ) {int levelCount = queue.size();int levelSum = 0;for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();levelSum += node.val;if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}if ( levelSum > maxSum ) {maxLevel = level;maxSum = levelSum;}level += 1;}return maxLevel;}
}

LeetCode 101. 对称二叉树

  • 更适合用深度优先遍历搜索DFS解这道题。
  • BFS层序遍历,每层从左往右、从右往左的结果是否相等。
  • 注意空节点缺省值填充。
  • 注意节点值的数据范围, − 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 100<=Node.val<=100
  • 时间复杂度O(n)
  • 空间复杂度O(n)
class Solution {public boolean isSymmetric(TreeNode root) {// BFS做法if ( root == null )return true;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while( !queue.isEmpty() ) {int levelCount = queue.size();LinkedList<Integer> leftResult = new LinkedList<>();LinkedList<Integer> rightResult = new LinkedList<>();// 每层循环遍历,从左往右、从右往左的结果是否相等for(int i=0; i<levelCount; i++) {TreeNode node = queue.poll();// 节点值范围 -100 ~ 100,空节点可用极大或极小值填充if ( node == null ) {leftResult.offerLast(-1000);rightResult.offerFirst(-1000);}else {leftResult.offerLast(node.val);rightResult.offerFirst(node.val);queue.offer(node.left);queue.offer(node.right);}}// 每层从左往右、从右往左的结果是否相等,空节点用缺省值填充if (leftResult.equals(rightResult))continue;elsereturn false;}return true;}
}

LeetCode 1302. 层数最深叶子节点的和

  • BFS,保留最后一层所有节点值的和。
class Solution {public int deepestLeavesSum(TreeNode root) {int sumResult = 0;Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while( !queue.isEmpty() ) {int levelCount = queue.size();int levelSum = 0;for ( int i=0; i<levelCount; i++ ) {TreeNode node = queue.poll();levelSum += node.val;if ( node.left != null )queue.offer(node.left);if ( node.right != null )queue.offer(node.right);}sumResult = levelSum;}return sumResult;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/310229.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基本运算器实验静态随机存储器实验

1.1 基本运算器实验 1. 实验记录 ①运算结果 首先按照实验指导书进行连线&#xff0c;然后打开试验箱电源&#xff0c;把A&#xff0c;B两个数存到寄存器中&#xff0c;然后改变s3 s2 s1 s0 的值&#xff0c;产生脉冲&#xff0c;观察对应的数据总线上的值以及两个标志位。 …

微信小程序开发系列-09自定义组件样式特性

微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》《微信小程序开发系列-02注册小程序》《微信小程序开发系列-03全局配置中的“window”和“tabBar”》《微信小程序开发系列-04获取用户图像和昵称》《微信小程序开发系列-05登录小程序》《微信小程序…

【Unity入门】热更新框架之xLua

目录 一、xLua概述1.1xLua简介1.2xLua安装 二、Lua文件加载2.1执行字符串2.2加载Lua文件2.3自定义loader 三、xLua文件配置3.1打标签3.2静态列表3.3动态列表 四、Lua与C#交互4.1 C#访问Lua4.1.1 获取一个全局基本数据类型4.1.2 访问一个全局的table4.1.3 访问一个全局的functio…

Maven项目提示Ignored pom.xml问题

1 环境 &#xff08;1&#xff09;IDEA开发工具&#xff1a;2022.2.1 &#xff08;2&#xff09;JDK&#xff1a;Java17&#xff08;Spring6要求JDK最低版本是Java17&#xff09; &#xff08;3&#xff09;Spring&#xff1a;6.1.2 &#xff08;4&#xff09;Maven 3.8.8 2 …

pytest --collectonly 收集测试案例

pytest --collectonly 是一条命令行指令&#xff0c;用于在运行 pytest 测试时仅收集测试项而不执行它们。它会显示出所有可用的测试项列表&#xff0c;包括测试模块、测试类和测试函数&#xff0c;但不会执行任何实际的测试代码。 这个命令对于查看项目中的测试结构和确保所有…

大模型LLM的微调技术:LoRA

0 引言 LoRA(Low-Rank Adaptation)出自2021年的论文“LoRA: Low-Rank Adaptation of Large Language Models” LoRA技术冻结预训练模型的权重&#xff0c;并在每个Transformer块中注入可训练层&#xff08;称为秩分解矩阵&#xff09;&#xff0c;即在模型的Linear层的旁边增…

Java EE 网络原理之HTTPS

文章目录 1. HTTPS 是什么&#xff1f;2. "加密" 是什么&#xff1f;3. HTTPS 的工作过程3.1 引入对称加密3.2 引入非对称加密3.3 中间人攻击3.4 引入证书 4. Tomecat4.1 tomcat 的作用 1. HTTPS 是什么&#xff1f; HTTPS也是⼀个应用层协议&#xff0c;是在 HTTP …

【计算机毕业设计】python+django数码电子论坛系统设计与实现

本系统主要包括管理员和用户两个角色组成&#xff1b;主要包括&#xff1a;首页、个人中心、用户管理、分类管理、数码板块管理、数码评价管理、数码论坛管理、畅聊板块管理、系统管理等功能的管理系统。 后端&#xff1a;pythondjango 前端&#xff1a;vue.jselementui 框架&a…

Java强软弱虚引用

面试&#xff1a; 1.强引用&#xff0c;软引用&#xff0c;弱引用&#xff0c;虚引用分别是什么&#xff1f; 2.软引用和弱引用适用的场景&#xff1f; 3.你知道弱引用的话&#xff0c;能谈谈WeakHashMap吗&#xff1f; 目录 一、Java引用 1、强引用&#xff08;默认支持模式…

ES6的默认参数和rest参数

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

编程羔手解决Maven引入多个版本的依赖包,导致包冲突了

最近升级了些依赖发现有个hutool的方法老报错&#xff0c;java.lang.NoSuchMethodError: cn.hutool.core.util.ObjectUtil.defaultIfNull(Ljava/lang/Object;Ljava/util/function/Supplier;) 在 Maven 项目中&#xff0c;当不同的依赖模块引入 Hutool 的不同版本时&#xff0c…

12.21自动售货机,单物品,多物品

自动售货机 if朴素方法 一种思路是用寄存器cnt记录已有的最小单位货币量&#xff0c;这里就是0.5 当d1时&#xff0c;cnt1;d2时&#xff0c;cnt2;d3时&#xff0c;cnt4; timescale 1ns/1ns module seller1(input wire clk ,input wire rst ,input wire d1 ,input wire d2 …