二叉树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;
        else
            return 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);
                // 从右往左,插入双端队列头部
                else
                    levelResult.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;
            else
                return 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.mfbz.cn/a/280831.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理2——轻松入门情感分析 - Python实战指南

目录 写在开头1.了解情感分析的概念及其在实际应用中的重要性1.1 情感分析的核心概念1.1.1 情感极性1.1.2 词汇和上下文1.1.3 情感强度1.2 实际应用中的重要性 2. 使用情感分析库进行简单的情感分析2.1 TextBlob库的基本使用和优势2.1.1 安装TextBlob库2.1.2 文本情感分析示例2…

小程序面试题 | 17.精选小程序面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

[Angular] 笔记 24:ngContainer vs. ngTemplate vs. ngContent

请说明 Angular 中 ngContainer&#xff0c; ngTemplate 和 ngContent 这三者之间的区别。 chatgpt 回答&#xff1a; 这三个在 Angular 中的概念是关于处理和组织视图的。 1. ngContainer&#xff1a; ngContainer 是一个虚拟的 HTML 容器&#xff0c;它本身不会在最终渲染…

算法训练day53|动态规划part14

参考&#xff1a;代码随想录 1143.最长公共子序列 重点&#xff1a;状态的转移与递推公式的确定 本题和动态规划&#xff1a;718. 最长重复子数组 (opens new window)区别在于这里不要求是连续的了&#xff0c;但要有相对顺序&#xff0c;即&#xff1a;"ace" 是 …

java企业网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web企业网站系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

go的json数据类型处理

json对象转slice package mainimport ("encoding/json""fmt""github.com/gogf/gf/container/garray" )func main() {// JSON 字符串jsonStr : ["apple", "banana", "orange"]//方法一&#xff1a;// 解析 JSON 字…

Netty(一)-NIO

一、Netty 现在的互联网环境下&#xff0c;分布式系统大行其道&#xff0c;而分布式系统的根基在于网络编程&#xff0c;而Netty恰恰是Java领域网络编程的王者。如果要致力于开发高性能的服务器程序&#xff0c;高性能的客户端程序&#xff0c;必须掌握Netty。 1、NIO NIO&…

2023年新一代开发者工具 Vue ,正式开源!

以下文章来源于前端充电宝 &#xff0c;作者CUGGZ 近日&#xff0c;Vue 新一代开发者工具&#xff08;DevTools&#xff09;正式开源&#xff01;Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具&#xff0c;它提供了一些功能来帮助开发者更好地了解 Vue 应用。下面就来看…

音频播放软件Foobar2000 mac特点介绍

Foobar2000 mac是一款高度可定制的音频播放器&#xff0c;适用于Windows平台。它支持各种音频格式&#xff0c;包括MP3、FLAC、AAC、WMA等&#xff0c;同时也支持各种音频插件和效果器&#xff0c;可以提供更好的音质和用户体验。 Foobar2000 mac软件特点 1. 高度可定制&#…

汇编语言指令系列

目录 &#xff08;一&#xff09;七大寻址方式 ① 立即寻址&#xff1a; ② 寄存器寻址&#xff1a; ③ 直接寻址&#xff1a; ④ 寄存器间接寻址&#xff1a; ⑤ 变指寻址&#xff1a; ⑥ 相对寻址&#xff1a; ⑦ 位寻址&#xff1a; &#xff08;二&#xff09;重要…

网络交换机端口管理会面临的问题

交换机端口管理是跟踪网络交换机及其端口连接详细信息的过程&#xff0c;在大型网络中&#xff0c;交换机端口管理过程通常使用自动化交换机端口管理工具执行。 通过网络交换机端口提供的完全控制和可见性使交换机端口管理工具在管理网络时必不可少&#xff0c;在网络中部署交…

utf8mb4_0900_ai_ci、utf8mb4_0900_as_ci、utf8mb4_0900_as_cs 这三者有什么区别

utf8mb4_0900_ai_ci, utf8mb4_0900_as_ci, 和 utf8mb4_0900_as_cs 是 MySQL 数据库中使用的字符集和校对规则。这些校对规则决定了如何比较和排序字符数据。它们属于 utf8mb4 字符集&#xff0c;这是 UTF-8 编码的超集&#xff0c;支持最多 4 个字节的字符&#xff0c;能够存储…

回归预测 | MATLAB实OOA-LSTM基于鱼鹰优化算法优化长短期记忆网络的多输入单输出数据回归预测模型 (多指标,多图)

回归预测 | MATLAB实OOA-LSTM基于鱼鹰优化算法优化长短期记忆网络的多输入单输出数据回归预测模型 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实OOA-LSTM基于鱼鹰优化算法优化长短期记忆网络的多输入单输出数据回归预测模型 &#xff08;多指标&a…

【信息安全原理】——期末复习(冲刺篇)

&#x1f4d6; 前言&#xff1a;快考试了&#xff0c;做篇期末总结&#xff0c;都是重点与必考点。 题型&#xff1a;简答题&#xff08;45分&#xff09;、协议分析题&#xff08;210分&#xff09;&#xff08;给一个报文或工作流程&#xff0c;分析存在的问题&#xff09;、…

SpringBoot用JDK1.8的依赖设置pom.xml

pom.xml的修改主要是两个地方&#xff1a; 1.修改springframework的版本为2.5.0&#xff0c;版本太高可能和其他插件搭配有冲突&#xff1b; 2.Java的版本修改成8&#xff0c;也就是对应JDK1.8。

[pingCTF 2023] 闲来无事作个题

谁元旦还打CTF啊&#xff0c;这两周没有比赛&#xff0c;明天才加班&#xff0c;作个已经过去的比赛。好在已经有官方WP&#xff0c;不会的可以看。 PWN without-love-it-cannot-be-seen 这个没有代码属于瞎pwn&#xff0c;随便输入个东西会提示密码不正确&#xff0c;然后输…

智能透明加密、半透明加密和落地加密的区别是什么?

智能透明加密、半透明加密和落地加密的主要区别如下&#xff1a; PC端访问地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 保护对象和方式&#xff1a; 智能透明加密&#xff1a;系统根据预设的敏感数据特征&#xff0c;对正…

[Angular] 笔记 20:NgContent

chatgpt: 在Angular中&#xff0c;NgContent是用于内容投影&#xff08;Content Projection&#xff09;的一个重要概念。它允许你在一个组件中插入内容&#xff0c;并将这些内容投影到另一个组件中。 当你在一个组件中使用<ng-content></ng-content>标签时&…

Mysql高阶语句及存储过程

目录 空值(NULL) 和 无值() 的区别&#xff1a; 正则表达式&#xff1a; 存储过程&#xff1a; 创建存储过程&#xff1a; 存储过程的参数&#xff1a; 存储过程的控制语句&#xff1a; mysql高阶语句 case是 SQL 用来做为if&#xff0c;then&#xff0c;else 之类逻辑的…

听GPT 讲Rust源代码--src/tools(36)

File: rust/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs 在Rust源代码中&#xff0c;empty_loop.rs文件位于src/tools/clippy/clippy_lints/src/loops/目录下&#xff0c;它的作用是实现并提供一个名为EMPTY_LOOP的Lint规则。Clippy是一个Rust的静态分析工具&#…
最新文章