【算法】队列与BFS

【ps】本篇有 4 道 leetcode OJ。

目录

一、算法简介

二、相关例题

1)N 叉树的层序遍历

.1- 题目解析

.2- 代码编写

2)二叉树的锯齿形层序遍历

.1- 题目解析

.2- 代码编写

3)二叉树最大宽度

.1- 题目解析

.2- 代码编写

4)在每个树行中找最大值

.1- 题目解析

.2- 代码编写


一、算法简介

        和栈类似,队列也是一种特殊的线性数据结构,是只允许在一端进行插入数据操作、在另一端进行删除数据操作的特殊线性表,具有先进先出的特性。进行插入操作(入队)的一端称为队尾,进行删除操作(出队)的一端称为队头

        队列一般与 BFS(宽度优先搜索)结合出题,而 BFS 主要的题型有树形结构相关(多为二叉树)、图论相关(最短路问题、迷宫问题、拓扑排序等)。

二、相关例题

1)N 叉树的层序遍历

429. N 叉树的层序遍历

.1- 题目解析

        在对多叉树进行层序遍历的时候,是每一层从左向右依此遍历,然后再进入下一层继续从左向右依此遍历的,而遍历完一层要进入下一层时,又要回到当前层的第一个节点,通过它的孩子节点,这样才能进入下一层继续遍历,而这个过程其实是符合队列先进先出的特点的,因此队列特别适合于这类题型。

        我们创建一个队列来模拟层序遍历的过程,且用一个变量来记录队列中元素的个数。若根节点不为空,就将根节点入队,此时队列中只有一个元素,仅需出队一次就能得到当前层的结果;然后将根节点的孩子节点全部入队,再记录当前队列中元素的个数,相应的,仅需出队元素的个数次就能得到当前层的结果......因此类推,直至队列中没有元素,就完成了多叉树的层序遍历。

.2- 代码编写

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> ret; //记录最终结果
        queue<Node*> q;          //用队列模拟层序遍历的过程
        if(root==nullptr)
            return ret;
        q.push(root);    //根节点入队
        while(q.size())
        {
            int sz=q.size(); //记录当前队列中的元素个数(树当前层元素的个数)
            vector<int> tmp; //统计当前层的节点
            for(int i=0;i<sz;i++)
            {
                Node* t=q.front();//取队头
                q.pop();
                tmp.push_back(t->val);
                for(Node* child:t->children) //让孩子节点入队
                {
                    if(child) q.push(child);
                }
            }
            ret.push_back(tmp); //统计最终结果
        }
        return ret;
    }
};

2)二叉树的锯齿形层序遍历

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

.1- 题目解析

        在正常的层序遍历过程中,我们是可以把一层的节点放在一个数组中去的。 既然我们有这个数组,在合适的层数逆序就可以得到锯齿形层序遍历的结果。由此,我们可以弄一个计数器 level 来记录当前的层数,当 level 为偶数时,就对数组进行逆序,再整体插入结果中。其余过程与上道题几乎相同。

.2- 代码编写

/**
 * 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:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> ret;
        if(root==nullptr)return ret;
        queue<TreeNode*> q;
        q.push(root);
        int level=1; //记录当前的层数
        while(q.size())
        {
            int sz=q.size();
            vector<int> tmp;
            for(int i=0;i<sz;i++)
            {
                auto t=q.front();
                q.pop();
                tmp.push_back(t->val);
                if(t->left)q.push(t->left);
                if(t->right)q.push(t->right);
            }
            if(level%2==0) //偶数层则需进行逆序
                reverse(tmp.begin(),tmp.end());
            ret.push_back(tmp);
            level++;
        }
        return ret;
    }
};

3)二叉树最大宽度

662. 二叉树最大宽度

.1- 题目解析

        在计算二叉树的最大宽度时,还要计入空节点。

        对于统计每一层的最大宽度,不难想到利用层序遍历,把当前层的结点全部存在队列里面,利用队列的长度来计算每一层的宽度,统计出最大的宽度。 此外,由于空节点也是需要计算在内的,因此空节点也需要存在队列里面。 但极端境况下,树的最左边一条长链,最右边也是一条长链,就需要存若干个空节点,这样就会超过最大内存限制。

        不过,我们还可以想到堆,借鉴在堆中寻找根的左右孩子的方式来解题。堆的逻辑结构是一棵树,而物理结构一个顺序结构,要通过一个根节点去寻找它的左右孩子,可以根据公式 “2 * 根节点下标 + 1” 或 “2 * 根节点下标 + 2”,在顺序结构中找到左右孩子的下标。

        那么,我们也可以仿照堆利用数组来存储二叉树的方式,给树节点都编上号,那么树中的空节点就可以忽略不计了,最终只需取最宽一层的最左边的节点和最右边的节点,两者的下标相减再 + 1 即可求得二叉树的最大宽度。

        对一颗满二叉树进行编号,我们不难发现,如果编号是从 1 开始的,假设一个根节点的编号为 x,那么这个根节点的左孩子的编号为 2x,右孩子的编号为 2x + 1。

        特别的,我们用 pair 类型将节点和其对应的编号一起存入数组中,以方便后续找到每一层的最左边节点和最右边节点。当一个节点进入数组时,只需看看它是其根节点的左孩子还是右孩子,然后根据左右孩子的编号的公式去求得它的编号即可。

        但由于有效节点和空节点的个数可能很多,下标是可能溢出的,好在数据的存储是一个环形的结构,且题目说明了,数据的范围在 int 这个类型的范围之内,因此最终求下标的差值,就无需考虑溢出的情况,只需用 unsigned int 作为下标和结果的变量类型即可。

.2- 代码编写

/**
 * 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) {
        vector<pair<TreeNode*, unsigned int>> q; // ⽤数组模拟队列
        q.push_back({root, 1});
        unsigned int ret = 0;
        while (q.size()) {
            // 先更新这⼀层的宽度
            auto& [x1, y1] = q[0];
            auto& [x2, y2] = q.back();
            ret = max(ret, y2 - y1 + 1);
            // 让下⼀层进队
            vector<pair<TreeNode*, unsigned int>> tmp; // 让下⼀层进⼊这个队列
            for (auto& [x, y] : q)
            {
                if (x->left)
                    tmp.push_back({x->left, y * 2});
                if (x->right)
                    tmp.push_back({x->right, y * 2 + 1});
            }
            q = tmp;
        }
        return ret;
    }
};

4)在每个树行中找最大值

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

.1- 题目解析

        在用队列模拟层序遍历的时候,顺便统计每一层的最大值即可。

.2- 代码编写

/**
 * 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:
    vector<int> largestValues(TreeNode* root) {
        vector<int> ret;
        if(root==nullptr)return ret;
        queue<TreeNode*> q;
        q.push(root);
        while(q.size())
        {
            int sz=q.size();
            int tmp=INT_MIN;
            for(int i=0;i<sz;i++)
            {
                auto t=q.front();
                q.pop();
                tmp=max(tmp,t->val);
                if(t->left)q.push(t->left);
                if(t->right)q.push(t->right);

            }
            ret.push_back(tmp);
        }
        return ret;
    }
};

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

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

相关文章

自养号测评:如何在敦煌网打造爆款与提升店铺权重

敦煌网自养号测评是敦煌网卖家为了提升店铺权重、流量及销量而采取的一种策略。自养号测评指的是卖家自行注册并管理买家账号&#xff0c;通过模拟真实买家行为&#xff0c;为自家店铺进行测评、补单等操作。以下是对敦煌网自养号测评的详细解析&#xff1a; 一、自养号测评的…

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法

Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法 Text-to-SQL 任务旨在将自然语言查询转换为结构化查询语言(SQL),从而使非专业用户能够便捷地访问和操作数据库。近期,阿里云的 OpenSearch 引擎凭借其一致性对齐技术,在当前极具影响力的 Text-to-SQL 任务…

3.接口测试的基础/接口关联(Jmeter工具/场景一:我一个人负责所有的接口,项目规模不大)

一、Jmeter接口测试实战 1.场景一&#xff1a;我一个人负责所有的接口&#xff1a;项目规模不大 http:80 https:443 接口文档一般是开发给的&#xff0c;如果没有那就需要抓包。 请求默认值&#xff1a; 2.请求&#xff1a; 请求方式:get,post 请求路径 请求参数 查询字符串参数…

马匹行为识别系统源码分享

马匹行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【自动驾驶】决策规划算法 | 数学基础(三)直角坐标与自然坐标转换Ⅱ

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

UE5源码Windows编译、运行

官方文档 Welcome To Unreal Engine 5 Early Access Learn what to expect from the UE5 Early Access program. 链接如下&#xff1a;https://docs.unrealengine.com/5.0/en-US/Welcome/#gettingue5earlyaccessfromgithub Step 0&#xff1a;找到UE5源码 直接先上链接 https…

5.内容创作的未来:ChatGPT如何辅助写作(5/10)

引言 在信息爆炸的时代&#xff0c;内容创作已成为连接品牌与受众、传递信息与知识、以及塑造文化与观念的重要手段。随着数字媒体的兴起&#xff0c;内容创作的需求日益增长&#xff0c;对创作者的写作速度和质量提出了更高的要求。人工智能&#xff08;AI&#xff09;技术的…

旧衣回收小程序:开启旧衣回收新体验

随着社会的大众对环保的关注度越来越高&#xff0c;旧衣物回收市场迎来了快速发展时期。在数字化发展当下&#xff0c;旧衣回收行业也迎来了新的模式----互联网旧衣回收小程序&#xff0c;旨在为大众提供更加便捷、简单、透明的旧衣物回收方式&#xff0c;通过手机直接下单&…

在线包装盒型生成工具,各种异型包装盒型,PDF导出方便

1、templatemaker.nl Passepartout ✂ Templatemaker ︎https://www.templatemaker.nl/en/passepartout/这是一个荷兰设计师建的一个在线盒型自动生成工具&#xff0c;包含各类新奇盒型&#xff0c;大家可以一起去观摩一下。 网站首页顶部各种盒型展示&#xff0c;大家根据需…

开源|一个很强大的离线IP地址定位库和IP定位数据管理框架,支持亿级别的数据段

开源|一个很强大的离线IP地址定位库和IP定位数据管理框架&#xff0c;支持亿级别的数据段 不太会写-9527 卓越云阶 2024年09月18日 12:35 贵州 随着互联网技术的飞速发展&#xff0c;IP地址定位已成为许多应用程序中不可或缺的一部分。然而&#xff0c;现有的许多定位库在处理…

刻意练习:舒尔特方格提升专注力

1.功能描述 刻意练习&#xff1a;舒尔特方格提升专注力 如果发现自己存在不够专注的问题&#xff0c;可以通过一个小游戏来提升自己专注力--舒尔特方格。 舒尔特方格的实施步骤如下&#xff1a; 一张纸上画出5X5的空方格。在方格中&#xff0c;没有任何规律的随机填写数字1…

LeetCode_sql_day24(1212.查询球队积分)

描述 表: Teams ------------------------- | Column Name | Type | ------------------------- | team_id | int | | team_name | varchar | ------------------------- team_id 是该表具有唯一值的列。 表中的每一行都代表一支独立足球队。表: Matches…

VSCode扩展连接虚拟机MySQL数据库

在虚拟机安装MySQL vscode通过ssh远程登录Ubuntu 在vscode终端运行以下命令。 sudo apt-get install mysql-server-5.7 用以下命令确认MySQL是否安装完成。 sudo mysql MySQL安装成功。 在VSCode安装SQL扩展 扩展名&#xff1a;MySQL Shell for VS Code。 安装完成后&am…

我的AI工具箱Tauri版-VideoMusicCheckpointLouver音乐卡点百叶窗视频制作

本教程基于自研的AI工具箱Tauri版进行VideoMusicCheckpointLouver音乐卡点百叶窗视频制作。 视频样片《队长小翼》《沖田浩之-燃えてヒーロー》百叶窗卡点视频 《队长小翼》《沖田浩之-燃えてヒーロー》百叶窗卡点视频 该模块没有任何消耗。需要提前准备好响应的素材 该模块没…

ESP8266做httpServer提示Header fields are too long for server to interpret

CONFIG_HTTP_BUF_SIZE512 CONFIG_HTTPD_MAX_REQ_HDR_LEN1024 CONFIG_HTTPD_MAX_URI_LEN512CONFIG_HTTPD_MAX_REQ_HDR_LEN由512改为1024

Idea 中的一些配置

配置 javap jdk 自带的 javap 可以用来查看字节码信息。 配置过程&#xff1a; 打开设置&#xff0c;定位到 Tools&#xff0c;External Tools新建项&#xff0c;Program 中填 javap 的路径Argument 中填 -c $FileClass$Working directory 中填 $OutputPath$ Argument 中也…

2024/9/17 pytorch-卷积神经网络

一、torch.nn pytorch有很多接口&#xff0c;其中的torch.nn可以让我们方便的调用以便生成神经网络各层 1.torch.nn.Module 是一个构成神经网络层的一个基本类别&#xff0c;一般生成一个类别来继承nn.module torch.tensor(a)将a初始化为一个tensor类型数据 一般这种已经固…

Android 内置应用裁剪

文章目录 查询目标 APK 的 Android.mk&#xff08;或 Android.bp&#xff09;文件apk裁剪方式1.注释或删除.mk/.bp文件2.将 APK 名称加入“OVERRIDES”配置项中3.自定义“PRODUCT_PACKAGES_REMOVE”配置项 查询目标 APK 的 Android.mk&#xff08;或 Android.bp&#xff09;文件…

一、Numpy使用

1、numpy的简单使用 import numpy as np #利用as给numpy起一个别名np# 使用array来承接这个数组 array np.array([[1,2,3],[2,3,4]])print(array) print("number of dim:", array.ndim) # ndim 数组维度 print("shape:", array.shape) # 数组的形…

VoIP协议

VoIP协议是VoIP业务的规范标准。我们都知道VoIP业务有着压倒性的优势。随着网络应用的多元化和低成本化发展&#xff0c;VoIP业务直接冲击着传统通信市场&#xff0c;那么目前VoIP协议目前常用的协议,如H.323、SIP、MEGACO和MGCP。 H.248 H.248是定义网关控制协议的ITU建议书…