【栈与队列】二叉树最大宽度

文章目录

  • 662. 二叉树最大宽度
  • 解题思路:队列 + 广度搜索

在这里插入图片描述

662. 二叉树最大宽度

662. 二叉树最大宽度

​ 给你一棵二叉树的根节点 root ,返回树的 最大宽度

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

​ 每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。

​ 题目数据保证答案将会在 32 位 带符号整数范围内。

示例 1:

在这里插入图片描述

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

示例 2:

在这里插入图片描述

输入:root = [1,3,2,5,null,null,9,6,null,7]
输出:7
解释:最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7) 。

示例 3:
在这里插入图片描述

输入:root = [1,3,2,5]
输出:2
解释:最大宽度出现在树的第 2 层,宽度为 2 (3,2) 。

提示:

  • 树中节点的数目范围是 [1, 3000]
  • -100 <= Node.val <= 100

解题思路:队列 + 广度搜索

​ 一开始上来写这道题的时候,我想到的是广度搜索,然后既然题目要求的是空节点也算入内,那么我就想着每次插入队列的时候,把空节点也入队列,然后每次在广度搜索每一层的时候,就使用变量遍历寻找最左边的非空节点和最右边的非空节点,最后得到整个区间的长度!

​ 但是很明显这种生硬的做法在这道题是不行的,因为如果这棵树是从根节点开始,左子树一直延伸下去,右子树一直延伸下去,这个高度就达到了接近 1500 层,那么节点的个数算上空节点个数的话,将近 2^1500 个节点,不说最后一层要遍历多久,单纯这个空间占用就十分的高了,所以这种方法是想不通的!

​ 换个思路想,其实上面这种方法是可以的,但是问题是我们还将没必要的空节点计入了队列中,这就导致了时间复杂度和空间复杂度的大幅度上涨!所以我们要想办法既不需要将空节点算入队列中,还可以知道每一层有多少个空节点!

​ 很显然上面的想法可行,但是不好做,所以我们再换个思路,既然不知道每层有多少个空节点,那么我们只需要找出最左节点的位置,以及最右节点的位置,然后用最右节点的位置减去最左节点的位置得到的就是该层的宽度!

​ 所以我们现在需要想办法找出最左节点和最右节点的位置,这里就可以 借鉴用数组以及数组下标方式存放树节点的方式 了!

​ 因为学二叉树的时候我们讲过,不只是可以用链表的方式存储,还可以使用数组方式存储,然后 通过其下标快速找到对应的左右孩子节点,最经典的例子就是我们学过的堆结构了!

​ 所以我们可以使用队列来进行广度搜索,然后队列中存放的元素不再是一个 TreeNode* 了,而是 存放一个键值对 pair<TreeNode*, int>,其中键就是对应的节点,然后值就是该节点在数组中对应其父节点的下标!

​ 然后我们将一层节点入队列之后,在下一次处理这一层节点的时候,我们可以直接通过队列的 front() 以及 back() 接口就得到该层最左和最右的两个节点的键值对,然后获取最左节点的下标,以及最右节点的下标,然后让 【最右节点的下标 - 最左节点的下标 + 1】 就得到了当前这一层的宽度!

​ 而此时数组下标从根节点开始,有两种记法:

  • 第一种是以 0 下标开始,则此时左孩子节点就是 2*x + 1,右孩子节点就是 2*x + 2
  • 第二种是以 1 下标开始,则此时左孩子节点就是 2*x,右孩子节点就是 2*x + 1

​ 这里我们采用第二种方式作为根节点起始下标,如下图所示:

在这里插入图片描述

​ 此时还有一个细节问题,就是这道题的溢出问题,很多题解没有讲清楚,为什么右孩子节点下标溢出了,结果还是对的,并且为什么 c++ 选手要用 unsigned int 存储下标,这里我们来解释一下!

​ 我们仔细一想,前面说过如果这棵树是从根节点开始,左子树一直延伸下去,右子树一直延伸下去,这个高度就达到了接近 1500 层,那么节点的个数算上空节点个数的话,将近 2^1500 个节点,此时对于右孩子节点的下标来说是溢出的,但其实我们让右孩子节点的下标减去左孩子节点的下标之后,是一个满足 int 类型范围的结果,这是题目保证的!

​ 之所以右孩子节点的下标溢出之后,减去左孩子节点的下标还能得到正确结果,其实就是因为我们之前学过的有符号整型它的取值范围问题,其实是呈现一个环状的,我们只要保证这个右孩子节点的下标溢出之后不要绕着这个取值范围的环状超过一圈即可,因为如果超过了一圈的话,那么直接用右孩子节点的下标减去左孩子节点的下标的话,会漏了超出的圈数的值,不过好在题目保证的答案将会在 32 位带符号整数范围内,就保证了右孩子节点的下标溢出之后,是不会说超过 32 位带符号整数范围的环状结构一圈的,这样子我们让右孩子节点的下标减去左孩子节点的下标之后得到的就还是一个正确的答案!

​ 至于为什么 c++ 选手要使用无符号整数 unsigned int 来存储下标,其实是因为语法规定的,int 溢出之后会报错,所以得使用 unsigned int 来存储才对!

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int widthOfBinaryTree(TreeNode* root) {// key表示节点,value表示在数组中的下标(通过下标的减法我们可以快速得到区间的长度)// 并且要使用unsigned int来存储下标,防止溢出// 这里默认根节点从1开始,那么左孩子就是2x,右孩子就是2x+1queue<pair<TreeNode*, unsigned int>> qe; qe.push(make_pair(root, 1)); unsigned int maxlen = 1;while(!qe.empty()){// 先直接利用队列获取首尾节点计算出区间长度maxlen = max(maxlen, qe.back().second - qe.front().second + 1); // 然后让下一层入队列int n = qe.size();for(int i = 0; i < n; ++i){pair<TreeNode*, unsigned int> front = qe.front();qe.pop();if(front.first->left != nullptr)qe.push(make_pair(front.first->left, 2*front.second));if(front.first->right != nullptr)qe.push(make_pair(front.first->right, 2*front.second + 1));}}return maxlen;}
};

在这里插入图片描述

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

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

相关文章

大语言模型安全测试:WDTA 标准下的全面解读与实践展望

1.前言 在人工智能&#xff08;AI&#xff09;飞速发展的时代&#xff0c;大语言模型&#xff08;LLM&#xff09;凭借其强大的语言理解和生成能力&#xff0c;广泛应用于智能客服、智能写作、智能翻译等众多领域&#xff0c;深刻改变着人们的生活和工作方式。然而&#xff0c…

在WINDOWS系统使用CMake gui编译NLopt配合VSCode使用

1. 准备工作 安装CMake&#xff1a;从CMake官网下载并安装CMake。下载Nlopt源码&#xff1a;从Nlopt官网或GitHub仓库下载Nlopt源码。安装编译器&#xff1a;确保已安装Visual Studio或其他支持的编译器&#xff08;如MinGW&#xff09;。 2. 配置CMake 方式1 打开CMake GU…

【DeepSeek开源:会带来多大的影响】

DeepSeek 开源&#xff0c;震撼登场对云计算行业的冲击 巨头云厂商的新机遇 DeepSeek 开源后&#xff0c;为云计算行业带来了巨大的变革&#xff0c;尤其是为巨头云厂商创造了新的发展机遇。以阿里云为例&#xff0c;它作为云计算行业的领军者&#xff0c;与 DeepSeek 的合作…

C++ QT 6.6.1 QCustomPlot的导入及使用注意事项和示例 | 关于高版本QT使用QCustomPlot报错问题解决的办法

C QT 6.6.1 QCustomPlot的导入及使用注意事项和示例 | 关于高版本QT使用QCustomPlot报错问题解决的办法 记录一下 qmake .pro文件的配置 QT core gui printsupportgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compil…

深入理解 `Sinks.Empty<Void>` 和 `Mono<Void>`:如何触发完成信号并结合 WebSocket 示例

在响应式编程中&#xff0c;Sinks 是 Project Reactor 提供的一个强大工具&#xff0c;用于手动控制数据流的信号发射。Sinks.Empty<Void> 是一种特殊的 Sinks&#xff0c;它不发射任何数据&#xff0c;仅用于表示完成或错误信号。结合 Mono<Void>&#xff0c;它可…

LLM+多智能体协作:基于CrewAI与DeepSeek的邮件自动化实践

文章目录 引言理解 Flows&#xff08;工作流&#xff09;与 Crews&#xff08;协作组&#xff09;一、环境准备与工具安装1.1 Python环境搭建1.2 创建并激活虚拟环境1.3 安装核心依赖库&#xff08;crewai、litellm&#xff09; 二、本地DeepSeek R1大模型部署2.1 Ollama框架安…

Deepseek开源周,第二天:Deep EP

DeepSeek 开源的 DeepEP 项目是一个专为 MoE&#xff08;混合专家&#xff09;模型设计的开源通信库&#xff0c;旨在优化训练和推理效率。其对开发者的核心价值体现在以下方面&#xff1a; 1. 显著提升训练与推理性能 全连接通信优化 通过高效优化的 All-to-All 通信机制&…

分布式深度学习:探索无限可能

分布式深度学习:探索无限可能 大家好,我是Echo_Wish,一名专注于人工智能和Python的自媒体创作者。今天,我们将深入探讨分布式深度学习,这个技术不仅是AI发展的前沿,更是应对大规模数据和复杂模型的关键解决方案。随着数据量和模型复杂度的不断增加,传统的单机深度学习已…

window下kafka安装

kafka下载 下载好,直接解压即可 默认是带有zookeeper(注册中心) 需要先启动zookeeper zookeeper配置 先配置下zookeeper 这个data文件夹是自定建的 随意建在哪里 注意 这里斜杠用和linux一样 启动zookeeper 进入bin/windows目录 启动zookeeper zookeeper-server-start.ba…

浅谈 Redis 主从复制原理(二)

大家好&#xff0c;我是此林。 【浅谈 Redis 主从集群原理&#xff08;一&#xff09; 】 上一篇文章中&#xff0c;说到了 Redis 主从复制的全量同步和增量同步&#xff0c;repl_baklog 复制缓冲区&#xff0c;以及 slave 挂掉之后数据同步的措施。 下面介绍的上一篇遗留问…

Vue 中单向数据流原则

做一个 ElementUI 弹框组件的二次封装 效果如下: 点击取消按钮发现弹出如下报错信息 : [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the …

网页版的俄罗斯方块

1、新建一个txt文件 2、打开后将代码复制进去保存 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>俄…

计算机毕业设计SpringBoot+Vue.js足球青训俱乐部管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

element ui的select选择框

我们首先先试一下&#xff0c;这个东西怎么玩的 <el-select v-model"select" change"changeSelect"><el-option value"香蕉"></el-option><el-option value"菠萝"></el-option><el-option value&quo…

DeepSeek引领目标检测新趋势:如何通过知识蒸馏优化模型性能

目录 一、知识蒸馏是什么&#xff1f; 二、知识蒸馏在目标检测中的重要性 提升实时性 跨任务迁移学习 三、如何使用知识蒸馏优化目标检测&#xff1f; 训练教师模型 生成软标签 训练学生模型 调节温度参数 多教师蒸馏&#xff08;可选&#xff09; 四、案例分享 定…

C++与Python实现LiDAR点云投影对比:关键差异与易错点详解

问题背景 在多传感器融合任务中&#xff0c;常需将LiDAR点云投影到相机图像。然而&#xff0c;不同语言&#xff08;如C和Python&#xff09;的实现可能存在细微差异&#xff0c;导致投影结果不一致。本文通过对比两段功能相近的代码&#xff08;C和Python&#xff09;&#x…

数据结构☞泛型

一.基础定义与应用方向 1.定义&#xff1a; 一般的类和方法&#xff0c;只能使用具体的类型 : 要么是基本类型&#xff0c;要么是自定义的类。如果要编写可以 应用于多种类型 的代码&#xff0c;这种刻板的限制对代码的束缚就会很大。----- 来源《 Java 编程思想》对泛型的介…

算法-数据结构-图-邻接表构建

邻接表的基本概念 顶点&#xff08;Vertex&#xff09;&#xff1a; 图中的每个顶点用一个节点表示。 每个顶点存储一个链表或数组&#xff0c;用于记录与该顶点直接相连的其他顶点。 边&#xff08;Edge&#xff09;&#xff1a; 如果顶点 A 和顶点 B 之间有一条边&#xf…

再论Spring MVC中Filter和HandlerInterceptor的优先级

在Spring MVC中&#xff0c;Filter和HandlerInterceptor的执行顺序及优先级如下&#xff1a; 1. 执行顺序与优先级 Filter&#xff08;Servlet规范&#xff09;的优先级高于 HandlerInterceptor&#xff08;Spring MVC框架&#xff09;。 请求处理流程&#xff1a; Filter链&a…

LeetCode 每日一题 2025/2/17-2025/2/23

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 2/17 1287. 有序数组中出现次数超过25%的元素2/18 2080. 区间内查询数字的频率2/19 624. 数组列表中的最大距离2/20 2595. 奇偶位数2/21 2209. 用地毯覆盖后的最少白色砖块…