算法:队列+宽搜

news2024/11/23 2:35:19

目录

题目一:N 叉树的层序遍历

题目二:二叉树的锯齿形层序遍历

题目三:二叉树最大宽度

题目四:在每个树行中找最大值


题目一:N 叉树的层序遍历

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

提示:

  • 树的高度不会超过 1000
  • 树的节点总数在 [0, 104] 之间

队列就是服务于宽搜这样的算法

在二叉树部分,我们有做过二叉树的层序遍历,这里是多叉树的层序遍历,其实方法还是一样的

每次将root结点入队列, 此时判断队列中有几个元素,有几个元素就说明这一层有几个结点,所以就出队列几次,每次出完这一次层数后就push_back进一个vector中

代码如下:

class Solution 
{
public:
    vector<vector<int>> levelOrder(Node* root) 
    {
        queue<Node*> q; // 层序遍历需要的队列
        vector<vector<int>> vv; //记录最终结果
        if(root == nullptr) return vv;
        q.push(root);
        while(!q.empty())
        {
            int count = q.size(); // 求出本层元素的个数
            vector<int> tmp; // 统计本层的节点
            while(count--)
            {
                Node* cur = q.front();
                q.pop();
                tmp.push_back(cur->val);
                if(!cur->children.empty())
                {
                    // 让下一层节点入队
                    for(auto it : cur->children)
                        q.push(it);
                }
            }
            vv.push_back(tmp);
        }
        return vv;
    }
};

题目二:二叉树的锯齿形层序遍历

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -100 <= Node.val <= 100

这道题依旧是层序遍历的变形,每一层换个方向,可以发现,只是在偶数行的节点逆序即可,所以与上一题一样,只需要在偶数行存储进 vector<vector<int>> 时逆序

只需要加一个变量,可以是bool类型,每一次取相反的结果,假设第一层变量置为 false,那就每次偶数行的时候变量为 true,此时将插入的结果逆序即可

也可以是 int 类型,变量是几就表示第几层,层数 % 2 等于 0 就逆序

下面我采用设定 bool 类型的方式,代码如下: 

class Solution 
{
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) 
    {
        vector<vector<int>> ret;
        queue<TreeNode*> q;
        // 如果为空,直接返回
        if(root == nullptr) return ret;
        // 创建一个变量flag,当false的时候就将结果逆序
        bool flag = false;
        q.push(root);
        while(!q.empty())
        {
            // 计算每层的结点个数
            int count = q.size();
            vector<int> tmp;
            while(count--)
            {
                TreeNode* front = q.front();
                q.pop();
                tmp.push_back(front->val);
                // 判断左右孩子是否存在
                if(front->left) q.push(front->left);
                if(front->right) q.push(front->right);
            }
            // 如果flag是true就逆序
            if(flag) reverse(tmp.begin(), tmp.end());
            ret.push_back(tmp);
            // 每次flag取反
            flag = !flag;
        }
        return ret;
    }
};

题目三:二叉树最大宽度

给你一棵二叉树的根节点 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

这个二叉树的最大宽度,其中的条件需要注意,只看第一个和最后一个结点,他们之间的结点如果是 nullptr 也是需要计算进去的

也就是说,统计宽度的时候是需要将二叉树当做满二叉树来统计的

这时就想到,二叉树可以存储在数组中,所以每一个结点就有对应的下标,通过下标就可以算出它的左右孩子的下标,此时每一层的最大宽度 = 最后一个结点的下标 - 第一个结点的下标 + 1 

还有两个细节:

细节一:这里的队列可以用数组代替,因为数组取下标更方便

细节二:有可能发生下标溢出的问题,因为题目有可能所给出的二叉树每一层只有一个结点,此时层数非常高,但是这里的溢出并不影响结果的正确性,因为我们要的只是一个长度,而内存中存储是按照环形存储的,题目又告诉答案一定在32位整数范围内

所以即使溢出了,两个小标之差也是正确的结果,由于这里可能出现溢出,所以存储时就使用无符号整数来存储,此时就不会出现溢出的错误了

代码如下:

class Solution 
{
public:
    int widthOfBinaryTree(TreeNode* root) 
    {
        vector<pair<TreeNode*, unsigned int>> q;
        q.push_back({root, 1});
        unsigned int ret = 0;
        while(!q.empty())
        {
            // pair类型就可以使用下面这种方式,x1表示first,x2表示second
            auto& [x1, y1] = q[0];
            auto& [x2, y2] = q[q.size() - 1];
            ret = max(ret, y2 - y1 + 1);
            // 因为需要头删,vector头删效率低,所以重新创建一个vector存下一层的结点
            vector<pair<TreeNode*, unsigned int>> tmp;
            for(auto& [x, y] : q)
            {
                if(x->left) tmp.push_back({x->left, 2 * y});
                if(x->right) tmp.push_back({x->right, 2 * y + 1});
            }
            // 将该层的结点全部存入tmp后,赋值给q,避免了头删
            q = tmp;
        }
        return ret;
    }
};

题目四:在每个树行中找最大值

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

示例1:

输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]

示例2:

输入: root = [1,2,3]
输出: [1,3]

提示:

  • 二叉树的节点个数的范围是 [0,104]
  • -231 <= Node.val <= 231 - 1

这道题题意非常简单,将每一层的最大值放入vector中

只需层序遍历时,找出每一层的最大值,存入即可

代码如下:

class Solution 
{
public:
    vector<int> largestValues(TreeNode* root) 
    {
        vector<int> ret;
        // 如果是空树,直接return
        if(root == nullptr) return ret;
        queue<TreeNode*> q;
        q.push(root);
        // 层序遍历
        while(!q.empty())
        {
            // num表示每层的最大值,初始化为int的最小值
            int num = INT_MIN;
            int count = q.size();
            while(count--)
            {
                TreeNode* front = q.front();
                q.pop();
                // num更新成最大值
                num = max(num, front->val);
                if(front->left) q.push(front->left);
                if(front->right) q.push(front->right);
            }
            // 将最大值存入ret
            ret.push_back(num);
        }
        return ret;
    }
};

本节题目到此结束了

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

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

相关文章

智能图片识别表格

文章目录 在线体验快速开始一、项目介绍篇1.1 PP-Structure概述1.2 PP-Structure核心功能&#xff1a;表格识别1.3 PP-Structure特点1.4 模块介绍1.4.1 TableDec.py1.4.2 app.py 二、核心代码介绍篇2.1 app.py2.2 TableDec.py2.3 扩展-模型选择3.4.1 版面分析模型3.4.2 表格识别…

Linux-mysql数据备份恢复

MySQL数据备份与恢复 一、备份介绍 1、为什么要备份 备份&#xff1a;能够防止由于机械故障以及人为误操作带来的数据丢失&#xff0c;例如将数据库文件保存在了其它地方。 冗余&#xff1a; 数据有多份冗余&#xff0c;但不等备份&#xff0c;只能防止机械故障带来的数据丢…

netty如何结合Zookeeper如何高并发的代码实现步骤 —— 慧哥充电桩开源平台

Netty是一个高性能、异步事件驱动的NIO&#xff08;非阻塞IO&#xff09;网络通信框架&#xff0c;而Zookeeper是一个分布式、开放源码的分布式应用程序协调服务&#xff0c;常用于维护配置信息、命名空间和提供分布式同步。 在高并发环境下&#xff0c;Netty与Zookeeper的结合…

昇思25天学习打卡营第13天 | mindspore 实现 ShuffleNet 图像分类

1. 背景&#xff1a; 使用 mindspore 学习神经网络&#xff0c;打卡第 13 天&#xff1b;主要内容也依据 mindspore 的学习记录。 2. 迁移学习介绍&#xff1a; mindspore 实现 ShuffleNet 图像分类&#xff1b; ShuffleNet 基本介绍&#xff1a; ShuffleNetV1 是旷视科技提…

RabbitMQ学习实践一:MQ的安装

文章是本人在学习springboot实现消息队列功能时所经历的过程的记录&#xff0c;仅供参考&#xff0c;如有侵权请随时指出。 参考文章地址&#xff1a; RabbitMQ安装与入门_rabbitmq win11配置-CSDN博客 RabbitMQ入门到实战一篇文章就够了-CSDN博客 RabbitMQ系列&#xff08…

进程通信(5):POSIX消息队列

随进程持续&#xff1a;IPC对象一直存在直到最后一个进程关闭该对象为止&#xff08;管道和FIFO)。 随内核持续&#xff1a;IPC对象存在一直到内核自举&#xff08;系统重新启动&#xff09;或者显示删除该对象。 如System V消息队列&#xff0c;System V信号量&#xff0c;S…

固态继电器的实际使用和有效应用

固态继电器(SSR)已成为现代电气和电子系统中不可或缺的组件&#xff0c;与传统的机电继电器相比具有众多优势。在本文中&#xff0c;我们将深入探讨SSR的实际方面、其应用以及有效部署的关键考虑因素。 什么是固态继电器&#xff1f; 固态继电器是使用半导体器件&#xff08;如…

ORB_SLAM2 ORBSLAM2 Ubuntu20.04 ROS Noetic虚拟机镜像下载

下图是build.sh 和 build_ros.sh 编译完成截图&#xff1a; slam测试视频: orbslam2 ubuntu20.04 test 下载地址&#xff08;付费使用&#xff0c;不能接受请勿下载&#xff09;&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16R7Pb6LjgR5SeoeBSZfgaQ?pwdu05r 提取…

前端小知识点——按钮之间出现很小的空隙如何规避

前端小知识点——按钮之间出现很小的空隙如何规避 文章介绍问题再现总结 文章介绍 本文主要介绍页面中两个按钮相邻时会出现一点空隙&#xff0c;导致在后续自定义填充的时候出现换行或其它问题&#xff0c;特此记录。 问题再现 这个图片能看到我们给外面的div设置的是300的宽…

stack模拟实现【C++】

文章目录 全部的实现代码放在了文章末尾什么是适配器模式&#xff1f;stack准备工作包含头文件定义命名空间类的成员变量 默认成员函数emptysizetoppushpop全部代码 全部的实现代码放在了文章末尾 stack的模拟实现我采用了C适配器模式 stack的适配器一般是deque&#xff0c;也…

SpringBoot系列—2.SpringBoot拦截器篇

SpringBoot系列—1.IDEA搭建SpringBoot框架 SpringBoot系列—2.SpringBoot拦截器篇 SpringBoot系列—3.SpringBoot Redis篇 SpringBoot系列—4.SpringBoot 整合Mybatis、MP&#xff08;MyBatis-Plus&#xff09; SpringBoot系列—5.SpringBoot 整合Mybatis-Plus分页 1.新建拦截…

C# 之工控机数据类型 高低位(大小端)、BitConverter、IsLittleEndian、字节数组转换(高低位)

八种基本数据类型&#xff1a;byte、short、int、long、float、double、boolean、char byte 8位、有符号的以二进制补码表示的整数 min : -128&#xff08;-2^7&#xff09; max: 127(2^7-1) default: 0 对应包装类&#xff1a;Byte short 16位、有符号的以二进制补码表示…

将微信聊天记录导出成html等格式

通过github上的开源项目WechatMsg&#xff0c;可以将微信中的聊天记录&#xff08;包括文字、图片、语音、表情包甚至拍一拍&#xff09;导出&#xff0c;方便我们随时分享和查看&#xff0c;此外还有聊天记录分析等有趣的功能&#xff0c;感兴趣的小伙伴可以研究一下。我个人认…

静态网站怎么更新数据

今天看到个问题 我不是行业从业者&#xff0c;但目前遇到一个问题 我公司网站为纯静态&#xff0c;除了直接从html里修改文字外能不能这样 建立一个xml或者txt文档&#xff0c;其中有很多信息&#xff0c;例如网站名称&#xff0c;电话&#xff0c;备案号等&#xff0c;一行一行…

AI赋能项目集成:我的实战经验与洞见

背景 在传统的教学模式中&#xff0c;教师往往难以兼顾每位学生的个性化需求&#xff0c;学习信息的收集与分析也受限于时间和精力的限制&#xff0c;难以做到全面而深入。然而&#xff0c;每位学生都是独一无二的个体&#xff0c;他们拥有不同的学习风格、兴趣偏好以及理解能…

【IC前端虚拟项目】sanity_case的编写与通包测试

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 在花了大力气完成reference model之后,整个验证环境的搭建就完成了,再多看一下这个结构然后就可以进行sanity_case和通包测试: 关于sanity_case和通包测试我在很多篇文章中说过好多次了在这里就不赘述…

如何安装Visual Studio Code

Visual Studio Code&#xff08;简称 VS Code&#xff09; Visual Studio Code 是一款由微软开发的免费、开源的现代化轻量级代码编辑器。 主要特点包括&#xff1a; 跨平台&#xff1a;支持 Windows、Mac 和 Linux 等主流操作系统&#xff0c;方便开发者在不同平台上保持一…

ETL电商项目总结

ETL电商项目总结 ETL电商业务简介及各数据表关系 业务背景 ​ 本案例围绕某个互联网小型电商的订单业务来开发。某电商公司&#xff0c;每天都有一些的用户会在线上采购商品&#xff0c;该电商公司想通过数据分析&#xff0c;查看每一天的电商经营情况。例如&#xff1a;电商…

科普文:字节码class文件和字节码增强技术

1. 引言 1.1. 什么是字节码 Java字节码是指Java语言编译后生成的一种二进制文件格式&#xff0c;它包含了Java程序的所有信息&#xff0c;包括类信息、方法信息、变量信息等。字节码是Java程序执行的基础&#xff0c;它被用于实现Java虚拟机&#xff08;JVM&#xff09;的加载…

随手记:vsCode修改主题色为自定义颜色

因为工作需要长时间面对vscode&#xff0c;视力不好&#xff0c;想要把工具改成护眼色&#xff0c;于是就把vscode改成了自定义的护眼色 效果图&#xff1a; 操作步骤&#xff1a; 快捷键打开设置页面&#xff1a; 按住ctrlshiftp 选择Open setting 按回车键 打开setting页面编…