算法Day15 | 层序遍历,102,107,199,637,429,515,116,117,104,111,226,101
Day15
- 层序遍历
- 102.二叉树的层序遍历
- 107.二叉树的层次遍历 II
- 199.二叉树的右视图
- 637.二叉树的层平均值
- 429.N叉树的层序遍历
- 515.在每个树行中找最大值
- 116.填充每个节点的下一个右侧节点指针
- 117.填充每个节点的下一个右侧节点指针II
- 104.二叉树的最大深度
- 111.二叉树的最小深度
- 226.翻转二叉树
- 101.对称二叉树
层序遍历
层序遍历就相当于图论中的广度优先搜索。
递归遍历就相当于图论中的深度优先搜索。
只使用二叉树结构,无法层序遍历。因为当你遍历到一个某个节点左节点时,无法遍历到其右节点。需要一个其他结构来辅助。选择使用队列queue保存每一层待遍历的元素。
102.二叉树的层序遍历
题目链接:102.二叉树的层序遍历
迭代
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;//记录每层节点vector<vector<int>> res;if (root) que.push(root);while (!que.empty()) {vector<int> res1;int size = que.size();//用于记录弹出节点个数,就是每层节点个数while (size--) {TreeNode* cur = que.front();que.pop();res1.push_back(cur->val);//记录节点数值if (cur->left) que.push(cur->left);//左节点入队列if (cur->right) que.push(cur->right);//右节点入队列}res.push_back(res1);}return res;}
};
递归
class Solution {
public:void recursive(TreeNode* cur, vector<vector<int>>& res, int depth) {if (!cur) return;//返回条件if (res.size() == depth) res.push_back(vector<int>());//开辟一个空的vector<int>
// if (res.size() == depth) res.emplace_back();等价于上一行res[depth].push_back(cur->val);recursive(cur->left, res, depth + 1);//depth+1是回溯recursive(cur->right, res, depth + 1);//depth+1是回溯}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> res;int depth = 0;//给res二维数组,用来赋外层索引recursive(root, res, depth);return res;}
};
107.二叉树的层次遍历 II
题目链接:107.二叉树的层次遍历 II
因为节点遍历只能从根节点开始。所以就正常层序遍历,最后结果反转一下。
迭代
class Solution {
public:vector<vector<int>> levelOrderBottom(TreeNode* root) {vector<vector<int>> res;queue<TreeNode*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();vector<int> res1;while (size--) {TreeNode* cur = que.front();que.pop();res1.push_back(cur->val);if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}res.push_back(res1);}reverse(res.begin(), res.end());return res;}
};
递归
class Solution {
public:void recursion(TreeNode* root, vector<vector<int>>& res, int depth) {if (!root) return;if (res.size() == depth) res.emplace_back();res[depth].emplace_back(root->val);recursion(root->left, res, depth + 1);//depth+1是回溯recursion(root->right, res, depth + 1);//depth+1是回溯}vector<vector<int>> levelOrderBottom(TreeNode* root) {vector<vector<int>> res;int depth = 0;recursion(root, res, depth);reverse(res.begin(), res.end());return res;}
};
199.二叉树的右视图
题目链接:199.二叉树的右视图
迭代
class Solution {
public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*> que;vector<int> res;if (root) que.push(root);while (!que.empty()) {int size = que.size();while (size--) {TreeNode* cur = que.front();que.pop();if (!size)/*size = 0*/ res.push_back(cur->val);if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}}return res;}
};
递归
class Solution {
public:void recursion(TreeNode* root, vector<int>& res, int depth) {if (!root) return;if (res.size() == depth) res.emplace_back(root->val);//先加入右节点元素,因为是保存右节点recursion(root->right, res, depth + 1);//depth+1是回溯recursion(root->left, res, depth + 1);//depth+1是回溯}vector<int> rightSideView(TreeNode* root) {vector<int> res;int depth = 0;recursion(root, res, depth);return res;}
};
637.二叉树的层平均值
题目链接:637.二叉树的层平均值
class Solution {
public:vector<double> averageOfLevels(TreeNode* root) {vector<double> res;queue<TreeNode*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();double sum = 0;int cnt = 0;while (size--) {TreeNode* cur = que.front();que.pop();sum += cur->val;++cnt;if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}res.push_back(sum / cnt);}return res;}
};
429.N叉树的层序遍历
题目链接:429.N叉树的层序遍历
class Solution {
public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> que;vector<vector<int>> res;if (root) que.push(root);while (!que.empty()) {int size = que.size();vector<int> res1;while (size--) {Node* cur = que.front();que.pop();res1.push_back(cur->val);for (auto& i : cur->children) {que.push(i);}}res.push_back(res1);}return res;}
};
515.在每个树行中找最大值
题目链接:515.在每个树行中找最大值
class Solution {
public:vector<int> largestValues(TreeNode* root) {vector<int> res;queue<TreeNode*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();int maxValue = INT_MIN;while (size--) {TreeNode* cur = que.front();que.pop();maxValue = max(maxValue, cur->val);if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}res.push_back(maxValue);}return res;}
};
116.填充每个节点的下一个右侧节点指针
题目链接:116.填充每个节点的下一个右侧节点指针
class Solution {
public:Node* connect(Node* root) {queue<Node*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();while (size--) {Node* cur = que.front();que.pop();if (size) cur->next = que.front();//如果不是最后一个,与下一个节点相连if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}}return root;}
};
117.填充每个节点的下一个右侧节点指针II
题目链接:117.填充每个节点的下一个右侧节点指针II
与上一道题一模一样
class Solution {
public:Node* connect(Node* root) {queue<Node*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();while (size--) {Node* cur = que.front();que.pop();if (size) cur->next = que.front();if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}}return root;}
};
104.二叉树的最大深度
题目链接:104.二叉树的最大深度
class Solution {
public:int maxDepth(TreeNode* root) {queue<TreeNode*> que;if (root) que.push(root);int res = 0;while (!que.empty()) {int size = que.size();while (size--) {TreeNode* cur = que.front();que.pop();if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}++res;}return res;}
};
111.二叉树的最小深度
题目链接:111.二叉树的最小深度
class Solution {
public:int minDepth(TreeNode* root) {queue<TreeNode*> que;if (!root) return 0;if (root) que.push(root);int res = 1;//至少有一层while (!que.empty()) {int size = que.size();while (size--) {TreeNode* cur = que.front();que.pop();if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);if (!cur->left && !cur->right) return res;}++res;}return res;}
};
226.翻转二叉树
题目链接:226.翻转二叉树
前、后序遍历很简单。
前序递归
class Solution {
public:TreeNode* invertTree(TreeNode* root) {if (!root) return nullptr;swap(root->left, root->right);//中invertTree(root->left);//左invertTree(root->right);//右return root;}
};
后序递归
class Solution {
public:TreeNode* invertTree(TreeNode* root) {if (!root) return nullptr;invertTree(root->left);//左invertTree(root->right);//右swap(root->left, root->right);//中return root;}
};
中序递归:代码上看是两次root->left
class Solution {
public:TreeNode* invertTree(TreeNode* root) {if (!root) return nullptr;invertTree(root->left);//左swap(root->left, root->right);//中//因为上一行代码已经处理过左树,处理完换成右树//接下来要处理的是原来的右树,但是已经变成左树了invertTree(root->left);//右return root;}
};
前序迭代
class Solution {
public:TreeNode* invertTree(TreeNode* root) {stack<TreeNode*> st;if (root) st.push(root);while (!st.empty()) {TreeNode* cur = st.top();if (cur) {st.pop();if (cur->right) st.push(cur->right);//右if (cur->left) st.push(cur->left);//左st.push(cur);//中st.push(nullptr);} else {st.pop();cur = st.top();st.pop();swap(cur->left, cur->right);}}return root;}
};
中序迭代
class Solution {
public:TreeNode* invertTree(TreeNode* root) {stack<TreeNode*> st;if (root) st.push(root);while (!st.empty()) {TreeNode* cur = st.top();st.pop();if (cur) {if (cur->right) st.push(cur->right);//右st.push(cur);//中st.push(nullptr);if (cur->left) st.push(cur->left);//左} else {cur = st.top();st.pop();swap(cur->left, cur->right);}}return root;}
};
后序迭代
class Solution {
public:TreeNode* invertTree(TreeNode* root) {stack<TreeNode*> st;if (root) st.push(root);while (!st.empty()) {TreeNode* cur = st.top();st.pop();if (cur) {st.push(cur);st.push(nullptr);if (cur->right) st.push(cur->right);if (cur->left) st.push(cur->left);} else {cur = st.top();st.pop();swap(cur->left, cur->right);}}return root;}
};
层序迭代
class Solution {
public:TreeNode* invertTree(TreeNode* root) {queue<TreeNode*> que;if (root) que.push(root);while (!que.empty()) {int size = que.size();while (size--) {TreeNode* cur = que.front();que.pop();swap(cur->left, cur->right);if (cur->left) que.push(cur->left);if (cur->right) que.push(cur->right);}}return root;}
};
101.对称二叉树
题目链接:101.对称二叉树
因为是先判断左右是否对称,再将结果传给中。顺序为左右中。所以是后序遍历。
递归
class Solution {
public:bool recursion(TreeNode* cur1, TreeNode* cur2) {//先排除空节点//这两个语句不能调换if (!cur1 && !cur2) return true;//非空之后,再排除值。if (!cur1 || !cur2 || cur1->val != cur2->val/*值判断一定要在非空之后*/) return false;auto outside = recursion(cur1->left, cur2->right);auto inside = recursion(cur1->right, cur2->left);return outside && inside;}bool isSymmetric(TreeNode* root) {if (!root) return true;return recursion(root->left, root->right);}
};
对于判断条件需要强调:
if (!cur1 && !cur2) return true;
if (!cur1 || !cur2) return false;
第一个if判断了同时为空的条件,满足条件,执行return。如果执行到第二条if语句,表示第一个if一定失效,即cur1和cur2不可能同时为空(有cur1为空,则cur2不为空;cur1不为空,则cur2为空),所以第二个if只需要判断cur1不为空(cur2一定为空)或者cur2不为空(cur1一定为空)即可。重要的是这两条if不能颠倒顺序。
if (!cur1 && !cur2) return true;
if (!cur1 && cur2) return false;
if (cur1 && !cur2) return false;
也就是,上面三条if可以用两条if来代替。因为第二条的if中的cur2和第三条if中的cur1一定是非空的,是多余的。
由于if后是return语句,所以可以不写else,先if( && )再写if( || )。更具一般性地,if( && ) else if ( || )。
迭代
class Solution {
public:bool isSymmetric(TreeNode* root) {if (!root) return true;stack<TreeNode*> st;st.push(root->left);st.push(root->right);while (!st.empty()) {auto leftNode = st.top();st.pop();auto rightNode = st.top();st.pop();if (!leftNode && !rightNode) continue;if (!leftNode || !rightNode || leftNode->val != rightNode->val)return false;st.push(leftNode->left);st.push(rightNode->right);st.push(leftNode->right);st.push(rightNode->left);}return true;}
};
相关文章:
算法Day15 | 层序遍历,102,107,199,637,429,515,116,117,104,111,226,101
Day15 层序遍历102.二叉树的层序遍历107.二叉树的层次遍历 II199.二叉树的右视图637.二叉树的层平均值429.N叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的下一个右侧节点指针117.填充每个节点的下一个右侧节点指针II104.二叉树的最大深度111.二叉树的最小深度 226…...
Prometheus+Grafana学习(十一)安装使用pushgateway
Pushgateway允许短暂和批量作业将其指标暴露给 Prometheus。由于这些工作的生命周期可能不足够长,不能够存在足够的时间以让 Prometheus 抓取它们的指标。Pushgateway 允许它们可以将其指标推送到 Pushgateway,然后 Pushgateway 再将这些指标暴露给 Prom…...
深入理解C/C++预处理器指令#pragma once以及与ifndef的比较
#pragma once用法总结 为了防止重复引用造成二义性 在C/C中,在使用预编译指令#include的时候,为了防止重复引用造成二义性,通常有两种方式 第一种是#ifndef指令防止代码块重复引用,比如说 #ifndef _CODE_BLOCK #define _CODE_BLO…...
git 环境配置 + gitee拉取代码
好嘛 配环境的时候 老是忘记这个命令行 干脆自己写一个记录一下 也不用搜了 1.先从git官网下载git 安装 2.然后从gitee拉取代码的时候提示 这是因为换了新电脑没有加入新的公钥啦 哎 所以老是记不住命令行 first : git config --global user.name “Your Name” …...
港联证券|港股拥抱特专科技企业 内资券商“修炼内功”蓄势而为
港股市场新一轮改革举措渐次落地。特别是港交所推出特专科技公司上市机制,吸引符合资格的科技企业申请赴港上市,成为这一轮港股市场改革的“重头戏”。 作为香港资本市场的重要参与者,内资券商立足香港、背靠内地、辐射全球,走出一…...
多项创新技术加持,实现零COGS的Microsoft Editor语法检查器
编者按:Microsoft Editor 是一款人工智能写作辅助工具,其中的语法检查器(grammar checker)功能不仅可以帮助不同水平、领域的用户在写作过程中检查语法错误,还可以对错误进行解释并给出正确的修改建议。神经语法检查器…...
Python编程环境搭建:Windows中如何安装Python
在 Windows 上安装 Python 和安装普通软件一样简单,下载安装包以后猛击“下一步”即可。 Python 安装包下载地址:https://www.python.org/downloads/ 打开该链接,可以看到有两个版本的 Python,分别是 Python 3.x 和 Python 2.x&…...
Sui Builder House首尔站倒计时!
Sui主网上线后的第一场Builder House活动即将在韩国首尔举行,同期将举办首场线下面对面的黑客松。活动历时两天,将为与会者提供独特的学习、交流和娱乐的机会。活动详情请查看:Sui Builder House首尔站|主网上线后首次亮相。 Sui…...
Java设计模式-状态模式
简介 在软件开发领域,设计模式是一组经过验证的、被广泛接受的解决问题的方案。其中之一是状态模式,它提供了一种优雅的方式来管理对象的不同状态。 状态模式是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为。状态模式将对…...
智慧社区用什么技术开发
智慧社区是指利用信息技术和先进的管理理念,将社区内的各种公共服务进行整合和优化,提高社区居民的生活品质和社区管理的效率。为了实现智慧社区的建设,需要采用多种技术,包括但不限于以下几种: 1.物联网技术…...
多线程 线程池饱和策略
RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。 这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。 在JDK 1…...
进程间通信之信号
进程间通信之信号 1. 信号2. 信号由谁产生?3. 有哪些信号4. 信号的安装5. 信号的发送1) 使用kill函数2)使用alarm函数3) 使用raise6.发送多个信号7. 信号集1. 信号 什么是信号? 信号是给程序提供一种可以处理异步事件的方法,它利用软件中断来实现。不能自定义信号,所有信号…...
二分查找三道题
二分查找 两种写法:左闭右闭[left,right]、左闭右开[left,right) 主要有几点不同:1. right是从num.length开始还是从num.length-1开始。2.left<还是<right。3.rightmid还是mid1 左闭右闭写法: public int search(int[] nums, int targ…...
MyBatis 框架
MyBatis 框架 MyBatis 简介搭建 MyBatis 开发环境核心配置文件详解mapper 映射文件(实现增删改查)MyBatis获取参数值的两种方式MyBatis的各种查询功能特殊SQL的执行自定义映射resultMapresultMap 字段和属性的映射多对一映射处理一对多映射处理 动态SQLM…...
【C++】虚表和虚基表到底有哪些区别?
虚表和虚基表 虚表虚基表虚拟继承和虚函数都存在时的对象模型 虚表 我们知道,如果类中声明了的方法是用virtual进行修饰的,则说明当前这个方法要作为虚函数,而虚函数的存储和普通函数的存储是有区别的 当有虚函数声明时,编译器会…...
剑指 Offer 04. 二维数组中的查找解题思路
文章目录 标题解题思路优化 标题 在一个 n * m 的二维数组中,每一行都按照从左到右 非递减 的顺序排序,每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整…...
冯诺依曼体系结构详解
一.冯诺伊曼体系结构的概念: 约翰冯诺依曼(John von Neumann,1903.1.28-1957.2.8),美籍匈牙利数学家,计算机科学家,物理学家。是20世纪最重要的数学家之一,后来被称为计算机之父。 后…...
ISO证书“带标”与“不带标”的区别是什么?
ISO9001质量管理体系认证是企业产品获得“通行绿卡”的最直接最有效的途径。 通过认证在打破贸易壁垒,提高产品知名度,降低生产成本,提高经济效益,维护消费者权益,减少重复审核负担等方面的作用越来越为企业界所共知。…...
RocketMQ 领域模型概述
本文为您介绍 Apache RocketMQ 的领域模型。 Apache RocketMQ 是一款典型的分布式架构下的中间件产品,使用异步通信方式和发布订阅的消息传输模型。通信方式和传输模型的具体说明,请参见下文通信方式介绍和消息传输模型介绍。 Apache RocketMQ 产品具备…...
黄河千年清一回与人类健康
黄河千年清一回奏响一曲曲让人类走进幸福新时代的壮丽凯歌。疫情之后的首届全世界健康产业发展大会 5 月28 日上午 9 时在中国首都北京召开 The Yellow River has played a magnificent song of triumph in the millennium, ushering humanity into a new era of happiness. T…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
