【算法】队列+bfs算法 解决树的相关算法题(C++)

文章目录

  • 1. 前言
  • 2. 算法题
    • 429.N叉树的层序遍历
    • 103.二叉树的锯齿形层序遍历
    • 662.二叉树最大宽度
    • 515.在每个树行中找最大值

1. 前言

队列 宽度优先算法(BFS)是解决很多算法问题的常见工具。

BFS通过逐层遍历图或树的节点来寻找解决问题的最短路径或最短步骤。使用队列可以很好地支持BFS算法的实现。

下面是一个使用队列和宽度优先算法解决问题的一般步骤:

  1. 创建一个空队列,并将起始节点放入队列中。
  2. 创建一个集合用于记录已经访问过的节点,防止重复访问。(visited数组,一般用于路径、迷宫问题)
  3. 初始化其他必要的辅助数据结构,例如距离数组或状态数组等。
  4. 开始循环,直到队列为空:
    • 从队列中取出一个节点作为当前节点。
    • 如果当前节点是目标节点,说明找到了解,结束搜索。
    • 否则,将当前节点的所有未访问过的邻居节点加入队列,并将这些节点标记为已访问。
  5. 如果需要记录路径或其他信息,可以在搜索过程中相应地更新辅助数据结构。
  6. 如果队列为空,说明不存在解。

使用队列和宽度优先算法可以解决许多问题,例如迷宫问题、最短路径问题、连通性问题等。具体的实现方式可能因问题而异,但基本思路是相似的。


2. 算法题

429.N叉树的层序遍历

在这里插入图片描述

思路

  • 解法队列,宽度优先搜索
    在这里插入图片描述

    1. 如上图所写,首先将根节点入队
    2. 循环队列,直至队列为空:
      3. q.size即为该层节点数,循环q.size次:提取出队头节点,并将该节点的所有子节点入队
    3. 每遍历一层,将结果加入到结果数组ret中

代码

vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret; // 最终结果queue<Node*> q; // 用队列记录节点// 将本层元素放入队列,提取出值后出队,将子节点入队if(root) q.push(root);else    return ret;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); // tmp记录该层节点值for(Node* child : t->children) // 当前节点的子节点入队{if(child) // 不为空q.push(child);}}ret.push_back(tmp); // 更新结果}return ret;
}

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

在这里插入图片描述

思路

  • 题意分析:要求按照先从左往右进行一层遍历、再从左往右进行下一层遍历,重复遍历完二叉树
    • 我们可以将其理解为奇数层正序遍历(从左向右),偶数层逆序遍历
  • 解法队列,宽度优先搜索
  • 该题与上一道很类似,只需要添加一个遍历用于标记当前层为奇数还是偶数,用于判断逆序还是正序
    1. 使用一个队列来存储当前层的所有节点,同时记录当前层的节点数。
    2. 依次从队列中取出节点,将其值加入到当前层的结果集tmp中,并将其左右子节点加入队列中。
    3. 如果当前层为偶数层,则需要将tmp逆序后再加入到结果集ret中。
    4. 最后返回结果集ret。

代码

vector<vector<int>> zigzagLevelOrder(TreeNode* root) {// 锯齿形层序遍历:偶数层逆序遍历,奇数层正常遍历vector<vector<int>> ret;queue<TreeNode*> q;if(!root) return ret;else q.push(root);int level = 1; // 根据flag判断是否逆序while(q.size()){int sz = q.size(); // 记录本层个数vector<int> tmp;for(int i = 0; i < sz; ++i){TreeNode* 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;
}

662.二叉树最大宽度

在这里插入图片描述

思路

  • 题意分析:即返回二叉树的最大宽度,即最大层的宽度
  • 解法:记录节点下标、数组表示队列
    在这里插入图片描述
    • 如上图的思路,我们用数组表示队列,队列中存放pair类型,分别为节点和其对应的下标
    1. 将根节点及其下标1插入队列,进行循环,直至队列为空
    2. 提取队尾和队头两元素(即为该层的最左最有的节点)并记录 / 更新结果
    3. 将该层的所有子节点入队
    4. 最后返回结果ret

代码

int widthOfBinaryTree(TreeNode* root) {// 队列(数组)存储节点及其下标(补全null节点后的下标)vector<pair<TreeNode*, unsigned int>> q;// q.push_back(make_pair<nullptr, 0>); if(!root) return 0;else q.push_back({root, 1}); // // 根节点从1下标开始unsigned int ret = 0; // 最终结果while(q.size()){// 计算本层宽度auto [node1, x1] = q[0]; // 提取一个pair类型auto [node2, x2] = q.back();ret = max(ret, x2 - x1 + 1);vector<pair<TreeNode*, unsigned int>> tmp; // tmp存储下一层节点信息,覆盖qfor(auto& [node, x] : q){// 左孩子下标:2x 右孩子下标:2x+1if(node->left) tmp.push_back({node->left, 2*x});if(node->right) tmp.push_back({node->right, 2*x + 1});}q = tmp;}return ret;
}

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

在这里插入图片描述

思路

  • 解法队列 + 层序遍历
  • 直接利用队列队树进行层序遍历即可
  • 每层循环定义一次变量maxVal用于寻找最大值

代码

vector<int> largestValues(TreeNode* root) {vector<int> ret; // 结果数组queue<TreeNode*> q; // 队列用于层序遍历if(!root) return ret;else q.push(root);while(!q.empty()){int sz = q.size();int maxVal = INT_MIN; // 用于比较节点大小 while(sz--){auto t = q.front(); // 提取当前节点q.pop();maxVal = max(maxVal, t->val);if(t->left) q.push(t->left);if(t->right) q.push(t->right);}ret.push_back(maxVal);}return ret;
}

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

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

相关文章

【idea】idea插件编写教程,博主原创idea插件已上架idea插件市场 欢迎下载

前言&#xff1a;经常使用Objects.equals(a,b)方法的同学 应该或多或少都会因为粗心而传错参&#xff0c; 例如日常开发中 我们使用Objects.equals去比较 status(入参)&#xff0c;statusEnum(枚举), 很容易忘记statusEnum.getCode() 或 statusEnum.getVaule() &#xff0c;再比…

C++ 多条件比较的几种实现方式

文章目录 1 sort()使用自定义比较器1.1 在类内部定义比较器 -- 声明为静态成员函数1.2 在函数内部定义比较器 -- lamda表达式1.3 全局函数比较器 2 重载运算符<2.1 在结构体中重载运算符<2.2 在类中重载运算符< 3 重写仿函数bool operator()4 使用pair排序5 priority_…

IPO:动力电池行业变天,不生产电芯的幂源科技为何也要卷?

幂源科技的真正角色&#xff0c;是月老&#xff1f; 最近&#xff0c;动力电池正处于市场重构阶段。一边是供给端动力电池产能过剩&#xff0c;一边是需求端新能源车企加码电池自研。供需不匹配孕育出了新机遇&#xff0c;产业链的连接者与赋能者成为市场所需。而幂源科技控股…

学生用台灯哪个品牌比较好?口碑最好的护眼台灯推荐

台灯是现在很多朋友都在使用的照明灯具&#xff0c;对于晚上工作学习、看书休闲都有很大的裨益&#xff0c;但是选择台灯也注重护眼效果&#xff0c;在此基础上才是讨论性价比的问题&#xff0c;如果光线让人眼不舒适&#xff0c;那么多便宜的台灯都不划算。 ● 怎样的护眼台灯…

基于FPGA的万兆以太网学习(1)

万兆(10G) 以太网测速视频:FPGA 实现UDP万兆以太网的速度测试 1 代码结构 2 硬件需求 SFP+屏蔽笼可以插入千兆或万兆光模块。SFP+信号定义与 SFP 一致。 3 Xilinx IP 10 Gigabit Ethernet Subsystem IP说明 文章链接: Xilinx IP 10 Gigabit Ethernet Subsystem IP 4 E…

Vue3响应式系统(二)

Vue3响应式系统(一)https://blog.csdn.net/qq_55806761/article/details/135587077 六、嵌套的effect与effect栈。 什么场景会用到effect嵌套呢&#xff1f;听我娓娓道来。 就用Vue.js来说吧&#xff0c;Vue.js的渲染函数就是在effect中执行的&#xff1a; /*Foo组件*/ const…

循环神经网络的变体模型-LSTM、GRU

一.LSTM&#xff08;长短时记忆网络&#xff09; 1.1基本介绍 长短时记忆网络&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;是一种深度学习模型&#xff0c;属于循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;的一种变体。…

Android NDK Crash信息收集捕获和日志异常定位分析(addr2line)

Android NDK 闪退日志收集与分析 我们在开发过程中,Android JNI层Crash问题或者我们引用的第三方.so库文件报错,都是一个比较头疼的问题。相对Java层来说,由于c/c++造成的crash没有输出如同Java的Exception Strace堆栈信息,所以定位问题也是个比较艰难的事情。 Google Br…

HCIA的路由协议

动态路由协议/静态路由协议 静态路由协议和动态路由协议的区别&#xff1a; 静态路由协议的缺点&#xff1a; 配置繁琐 针对拓扑的变化不能够自动收敛 只适用于小型网络 静态路由协议优点&#xff1a; 占用资源少 安全 稳定 动态路由协议的优点&#xff1a; 配置简单 针对拓…

前端项目配置 Dockerfile 打包后镜像部署无法访问

Dockerfile 配置如下&#xff1a; FROM node:lts-alpineWORKDIR /app COPY . . RUN npm install RUN npm run buildEXPOSE 3001CMD ["npm", "run", "preview"]构建镜像 docker build -t vite-clarity-project .启动镜像容器 docker run -p 30…

进程(一) 进程概念

文章目录 什么是进程呢&#xff1f; 描述进程-PCBtask_struct-PCB的一种task_struct内容分类 查看进程通过系统目录查看通过ps命令查看通过系统调用获取进程的PID和PPID通过系统调用创建进程- fork&#xff08;&#xff09;函数 fork()函数fork函数做了什么&#xff1f;fork之后…

Vue加载序列帧动图

解读方法 使用<img :src"currentFrame" alt"加载中" /> 加载图片动态更改src的值使用 requestAnimationFrame 定时更新在需要的页面调用封装的组件 <LoadToast v-if"showLoading" /> 封装组件 <template><div class"…

CTF CRYPTO 密码学-1

题目名称&#xff1a;enc 题目描述&#xff1a; 压缩包中含两个文件&#xff1a;一个秘钥d.dec&#xff0c;一个密文flag.enc 解题过程&#xff1a; Step1&#xff1a;这题是一个解密他题目&#xff0c;尝试openssl去ras解密 工具简介 在Kali Linux系统中&#xff0c;openss…

React16源码: React中的异步调度scheduler模块的源码实现

React Scheduler 1 ) 概述 react当中的异步调度&#xff0c;称为 React Scheduler发布成单独的一个 npm 包就叫做 scheduler这个包它做了什么&#xff1f; A. 首先它维护时间片B. 然后模拟 requestIdleCallback 这个API 因为现在浏览器的支持不是特别的多所以在浏览当中只是去…

【计算机图形学】习题课:Viewing

【计算机图形学】Viewing 部分问题与解答 CS100433 Computer Graphics Assignment 21 Proof the composed transformations defined in global coordinate frame is equivalent to the composed transformations defined in local coordinate frame but in different composing…

1月14-17日为技术测试期!字节与腾讯上演“大和解”,抖音全面开放《王者荣耀》直播

综合整理&#xff5c;TesterHome社区 来源&#xff5c;《王者荣耀》官方、界面新闻 北京商报、IT之家 1月13日&#xff0c;腾讯游戏《王者荣耀》官方微博发布消息宣布&#xff0c;从1月21日起&#xff0c;《王者荣耀》抖音直播将全面开放。 为了筛查开播期间可能遇到的所有技…

几何_直线方程 Ax + By + C = 0 的系数A,B,C几何含义是?

参考&#xff1a; 直线方程 Ax By C 0 的系数A&#xff0c;B&#xff0c;C有什么几何含义&#xff1f;_设直线 l 的方程为axbyc0 怎么理解-CSDN博客 1. A B的含义&#xff1a;组成一个与直线垂直的向量 我们先来看A和B有什么含义。 在直线上取任意两点 P1:&#xff08;x1…

OceanBase集群部署

我认为学习一个中间件比较好的方式是&#xff0c;先了解它的架构和运行原理&#xff0c;然后动手部署一遍&#xff0c;加深对它的了解&#xff0c;再使用它&#xff0c;最后进行总结和分享 本篇介绍OceanBase部署前提配置和集群部署 1.使用开源免费的社区版&#xff0c;企业版…

[Android] Android架构体系(1)

文章目录 Android 的框架Dalvik 虚拟机JNI原生二进制可执行文件Android NDK中的binutils Bionic谷歌考虑到的版权问题Bionic与传统的C标准库&#xff08;如glibc&#xff09;的一些不同 参考 Android 的框架 Android 取得成功的关键因素之一就是它丰富的框架集。 没有这些框架…

架构08- 理解架构的模式2-管理和监控

大使模式&#xff1a;构建一个辅助服务&#xff0c;代表消费者使用服务或应用程序发送网络请求。 进程外的代理服务&#xff08;之前介绍中间件的时候也提到了&#xff0c;很多框架层面的事情可以以软件框架的形式寄宿在进程内&#xff0c;也可以以独立的代理形式做一个网络中…