二叉树题目:二叉树最大宽度

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 前言
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:二叉树最大宽度

出处:662. 二叉树最大宽度

难度

5 级

题目描述

要求

给定一个二叉树的根结点 root \texttt{root} root,返回给定的树的最大宽度

树的最大宽度是所有层中的最大宽度

每一层的宽度定义为两端结点(最左和最右的非空结点)之间的长度,两端结点之间的空结点也计入长度的计算。

题目保证答案在 32 \texttt{32} 32 为有符号整数范围内。

示例

示例 1:

示例 1

输入: root   =   [1,3,2,5,3,null,9] \texttt{root = [1,3,2,5,3,null,9]} root = [1,3,2,5,3,null,9]
输出: 4 \texttt{4} 4
解释:最大宽度出现在第 3 \texttt{3} 3 层,宽度为 4 \texttt{4} 4 5,3,null,9 \texttt{5,3,null,9} 5,3,null,9)。

示例 2:

示例 2

输入: root   =   [1,3,null,5,3] \texttt{root = [1,3,null,5,3]} root = [1,3,null,5,3]
输出: 2 \texttt{2} 2
解释:最大宽度出现在第 3 \texttt{3} 3 层,宽度为 2 \texttt{2} 2 5,3 \texttt{5,3} 5,3)。

示例 3:

示例 3

输入: [1,3,2,5] \texttt{[1,3,2,5]} [1,3,2,5]
输出: 2 \texttt{2} 2
解释:最大宽度出现在树的第 2 \texttt{2} 2 层,宽度为 2 \texttt{2} 2 3,2 \texttt{3,2} 3,2)。

数据范围

  • 树中结点数目在范围 [1,   3000] \texttt{[1, 3000]} [1, 3000]
  • -100 ≤ Node.val ≤ 100 \texttt{-100} \le \texttt{Node.val} \le \texttt{100} -100Node.val100

前言

为了得到二叉树的最大宽度,需要得到二叉树每一层中的每个结点的位置。每一层的宽度取决于该层最左和最右的非空结点的位置,除了根结点以外的每个结点的位置由该结点的父结点和该结点是左子结点还是右子结点决定。

考虑满二叉树每一层中的每个结点的位置。定义根结点位于第 0 0 0 层,则满二叉树的第 k k k 层有 2 k 2^k 2k 个结点,从左到右的每个结点的位置依次是 0 0 0 2 k − 1 2^k - 1 2k1,满二叉树的第 k + 1 k + 1 k+1 层有 2 k + 1 2^{k + 1} 2k+1 个结点,从左到右的每个结点的位置依次是 0 0 0 2 k + 1 − 1 2^{k + 1} - 1 2k+11。由于满二叉树的第 k + 1 k + 1 k+1 层的结点数目是第 k k k 层的结点数目的 2 2 2 倍,因此对于第 k k k 层中位置是 pos \textit{pos} pos 的结点,其左子结点和右子结点在第 k + 1 k + 1 k+1 层中的位置分别是 pos × 2 \textit{pos} \times 2 pos×2 pos × 2 + 1 \textit{pos} \times 2 + 1 pos×2+1

上述关于结点位置的定义同样适用于不是满二叉树的情况。对于每个非空结点,只要知道该结点在当前层中的位置,即可知道该结点的每个子结点在下一层中的位置,因此可以知道每个结点在对应层中的位置。

解法一

思路和算法

由于需要计算二叉树每一层的宽度,然后得到最大宽度,因此可以使用层序遍历实现。

从根结点开始依次遍历每一层的结点,在层序遍历的过程中需要区分不同结点所在的层,确保每一轮访问的结点为同一层的全部结点。遍历每一层结点之前首先得到当前层的结点数,即可确保每一轮访问的结点为同一层的全部结点。对于每一层,记录该层的最左和最右非空结点的位置,然后计算该层的宽度。

为了记录每个结点的位置,需要使用两个队列,分别存储结点和结点的位置,这两个队列分别为结点队列和位置队列,初始时将根结点和位置 0 0 0 分别入两个队列。在遍历每一层之前,位置队列的队首元素即为该层的最左非空结点的位置,遍历该层的每个结点时,将每个结点的非空子结点和子结点对应的位置分别入两个队列,该层的最后一个结点即为该层的最右非空结点,计算两端结点之间的长度,得到该层的宽度,并用该层的宽度更新最大宽度。

遍历结束之后,即可得到二叉树的最大宽度。

代码

class Solution {
    public int widthOfBinaryTree(TreeNode root) {
        int maxWidth = 0;
        Queue<TreeNode> nodeQueue = new ArrayDeque<TreeNode>();
        Queue<Integer> posQueue = new ArrayDeque<Integer>();
        nodeQueue.offer(root);
        posQueue.offer(0);
        while (!nodeQueue.isEmpty()) {
            int leftmost = posQueue.peek();
            int size = nodeQueue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = nodeQueue.poll();
                int pos = posQueue.poll();
                if (i == size - 1) {
                    int width = pos - leftmost + 1;
                    maxWidth = Math.max(maxWidth, width);
                }
                TreeNode left = node.left, right = node.right;
                if (left != null) {
                    nodeQueue.offer(left);
                    posQueue.offer(pos * 2);
                }
                if (right != null) {
                    nodeQueue.offer(right);
                    posQueue.offer(pos * 2 + 1);
                }
            }
        }
        return maxWidth;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是队列空间,队列内元素个数不超过 n n n

解法二

思路和算法

也可以使用深度优先搜索计算二叉树最大宽度。具体做法是使用前序遍历,依次访问二叉树的根结点、左子树和右子树,由于前序遍历满足同一层结点被访问的顺序为从左到右,因此同一层结点中第一个被访问的结点一定是该层最左的非空结点。使用哈希表存储每一层的最左的非空结点的位置(以下简称「最左位置」),当访问到某个结点时,如果哈希表中没有该结点所在层的最左位置,则在哈希表中将当前层对应的最左位置设为该结点的位置。

对于访问到的每个非空结点,可以得到当前层内该结点的位置和最左位置,计算当前层内该结点和最左的非空结点之间的宽度,并更新二叉树的最大宽度。遍历结束之后,即可得到二叉树的最大宽度。

代码

class Solution {
    Map<Integer, Integer> leftmostMap = new HashMap<Integer, Integer>();
    int maxWidth = 0;

    public int widthOfBinaryTree(TreeNode root) {
        dfs(root, 0, 0);
        return maxWidth;
    }

    public void dfs(TreeNode node, int depth, int pos) {
        leftmostMap.putIfAbsent(depth, pos);
        maxWidth = Math.max(maxWidth, pos - leftmostMap.get(depth) + 1);
        TreeNode left = node.left, right = node.right;
        if (left != null) {
            dfs(left, depth + 1, pos * 2);
        }
        if (right != null) {
            dfs(right, depth + 1, pos * 2 + 1);
        }
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是哈希表和栈空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)

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

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

相关文章

【Python基础】一个简单的TCP通信程序

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

事务JdbcTemplate

Spring框架对JDBC进行封装&#xff0c;使用JdbcTemplate方便对数据库操作。 1.搭建模块 2.引入依赖 <dependencies><!-- spring jdba Spring持久化层支持jar包--><dependency><groupId>org.springframework</groupId><artifactId>…

GB28181流媒体平台LiveGBS切换为国产信创环境下达梦数据库、高斯数据库、瀚高数据库的配置说明

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库 1、如何配置切换信创达梦数据库&#xff1f;2、如何配置切换高斯数据库&#xff1f;3、如何配置切换信创瀚高数据库&#xff1f;4、搭建GB28181视频直播平台 1、如何配置切换信创达梦数据库&…

Linkage Mapper 报错

1 . 错误提示&#xff1a;“No module named lm_config” 错误原因&#xff1a;**** 2.错误提示&#xff1a;“Cannot find an installation of Circuitscape in your Program Files directory.” 错误原因&#xff1a;***** 3. 错误提示&#xff1a;UnicodeEncodeError: ‘asc…

Element-Ui el-table 动态添加行

一、在项目需要使用 这个需求主要是在项目中需要用到 1.点击新增按钮&#xff0c;可以实现新增行。 2.在每个列里面可以进行输入。 3.可以删除新增的行&#xff0c;包括数据。 二、HTML代码 1.主要是循环每一个列&#xff0c;而且这些列都是动态&#xff0c;根据父组件传过来…

Facebook平台特征概述

Facebook是全球最大的社交媒体平台之一&#xff0c;拥有数十亿的用户。它的独特特征和功能使其成为人们分享、互动和连接的理想场所。下面小编将讲一下关于Facebook平台的特征的详细概述。 1、用户个人资料 每个Facebook用户都有一个个人资料页面&#xff0c;可以在上面分享个…

java算法学习索引之动态规划

一 斐波那契数列问题的递归和动态规划 【题目】给定整数N&#xff0c;返回斐波那契数列的第N项。 补充问题 1&#xff1a;给定整数 N&#xff0c;代表台阶数&#xff0c;一次可以跨 2个或者 1个台阶&#xff0c;返回有多少种走法。 【举例】N3&#xff0c;可以三次都跨1个台…

一文搞懂 Elasticsearch 之 Mapping

这篇文章主要介绍 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自动判断字段的类型&#xff0c;同时介绍 Mapping 的相关参数设置。 首先来看下什么是 Mapping&#xff1a; 1 什么是 Mapping&#xff1f; 在一篇文章带你搞定 ElasticSearch 术语中&#xff0c;我们讲…

DevicData-D-XXXXXXXX勒索病毒来袭:如何面对DevicData-D-XXXXXXXX勒索病毒的威胁

尊敬的读者&#xff1a; .DevicData-D-XXXXXXXX勒索病毒&#xff0c;犹如数字世界的黑暗幽灵&#xff0c;通过其复杂的加密算法&#xff0c;将用户数据变为数字谜团&#xff0c;要求赎金以唤回失去的信息。在这个数字时代&#xff0c;了解其特质和对抗方法至关重要。面对复杂的…

Linux进程之通过系统调用创建进程[fork()函数]

文章目录 0.PID是什么?1.通过代码创建子进程--fork1.1fork()初识1.2通过系统调用创建进程1.3perror()函数的了解 2.fork()的进一步了解2.1通过代码了解2.2查看进程的指令 0.PID是什么? 进程PID&#xff08;Process ID&#xff09;是操作系统为每个正在运行的进程分配的唯一标…

0基础学习VR全景平台篇第120篇:极坐标处理接缝 - PS教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 紧跟上节课&#xff0c;我们已经学会了怎么利用PS蒙版工具来对航拍全景图补天。但是在后续工作学习中&#xff0c;我们会遇到天空这部分存在部分接缝的问题&#xff0c;如图&…

ZYNQ调试w25q128bv做flash启动系统

配置petalinux系统从flahs启动&#xff0c;发现BOO.BIN能启动&#xff0c;BOOT.BINimage.ub启动不了。其中烧写和配置的时候&#xff0c;image.ub.bin偏移地址都是0x520000 烧写&#xff0c;然后启动 U-Boot 2018.01-00083-gd8fc4b3b70 (Nov 13 2023 - 03:29:36 0000) Xilinx…

【unity】常用属性特征

编辑器功能 AddComponentMenu-添加组件菜单 将脚本添加到Unity编辑器的菜单中&#xff0c;方便开发者在编辑器中快速添加组件。 示例 using UnityEngine; [AddComponentMenu("添加组件/FollowTransform")] public class FollowTransform : MonoBehaviour { }效果 …

Seaborn数据可视化综合应用Basemap和Seaborn在线闯关_头歌实践教学平台

Seaborn数据可视化综合应用Basemap和Seaborn 第1关 Seaborn第2关 Seaborn图形介绍第3关 Basemap 第1关 Seaborn 任务描述 本关任务&#xff1a;编写一个绘制每个月销售总额的折线图。 编程要求 本关的编程任务是补全右侧上部代码编辑区内的相应代码&#xff0c;根据输入文件路…

java语言开发B/S架构医院云HIS系统源码【springboot】

医院云HIS全称为基于云计算的医疗卫生信息系统( Cloud- Based Healthcare Information System)&#xff0c;是运用云计算、大数据、物联网等新兴信息技术&#xff0c;按照现代医疗卫生管理要求&#xff0c;在一定区域范围内以数字化形式提供医疗卫生行业数据收集、存储、传递、…

基于若依的ruoyi-nbcio流程管理系统增加流程设计器支持自定义表单的选择与处理

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 因为之前不支持在流程设计器进行自定义业务表单的关联选择&#xff0c;所以这部分实现这个。 1、前端 对…

ZooKeeper+Kafka+ELK+Filebeat集群搭建实现大批量日志收集和展示

大致流程&#xff1a;将nginx 服务器&#xff08;web-filebeat&#xff09;的日志通过filebeat收集之后&#xff0c;存储到缓存服务器kafka&#xff0c;之后logstash到kafka服务器上取出相应日志&#xff0c;经过处理后写入到elasticsearch服务器并在kibana上展示。 一、集群环…

lora微调模版

lora微调模版 1、版一&#xff1a;使用peft包的lora微调&#xff08;1&#xff09;设置超参方式一&#xff1a;代码中设置&#xff08;便于debug&#xff09;方式二&#xff1a; .sh文件指定 &#xff08;2&#xff09;加载数据集I、对应的.jsonl或json文件, 原始格式为&#x…

Kafka简单汇总

Kafka的结构图 多个Parttion共同组成这个topic的所有消息。每个consumer都属于一个consumer group&#xff0c;每条消息只能被consumer group中的一个Consumer消费&#xff0c; 但可以被多个consumer group消费。即组间数据是共享的&#xff0c;组内数据是竞争的。二、消费模型…

PO设计模式详解(Python+selenium+unittest)

一、什么是PO设计模式&#xff08;Page Object Model&#xff09; 1、Page Object是一种设计模式&#xff0c;它主要体现在对界面交互细节的封装上&#xff0c;使测试用例更专注于业务的操作&#xff0c;从而提高测试用例的可维护性。 2、一般PO设计模式有三层 第一层&#…