【LeetCode】专题一 二叉树层序遍历

news2024/9/24 21:25:50

二叉树层序遍历

在本文中,我将会选取LeetCode上二叉树层序遍历的多道例题,并给出解答,通过多道题我们就可以发现,二叉树的层序遍历并不复杂,并且有着共通点。

102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

image.png

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

示例 2:

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

示例 3:

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

提示:

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

思考:

本题又是一种新的二叉树遍历方式,层序遍历,这种遍历方式其实较为简单,符合正常的遍历顺序。所以我们可以采用队列这种数据结构,运用其先进先出的特性进行遍历。

利用队列遍历:

本题要求按每一层遍历,所以我们采用for循环的形式,进行每一层的遍历。值得注意的是,随着结点加入队列中,队列的大小也会随之改变,所以在进行for循环之前,需要提前存储队列的大小size。

/**
 * 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>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty())
        {
            vector<int> childvector;//子容器,储存每一层遍历的结果
            int size = que.size();//记录队列当前大小
            for (int i = 0; i < size; i++)
            {
                TreeNode* cur = que.front();
                que.pop();

                if (cur->left)
                {
                    que.push(cur->left);
                }
                if (cur->right)
                {
                    que.push(cur->right);
                }
                childvector.push_back(cur->val);
            }
            result.push_back(childvector);
        }
        return result;
    }
};

递归法:

当然,该题也可以使用递归法来实现,该题中,递归的终止条件为:遍历到空节点,此时说明已将所有结点遍历完毕,进行返回,结束递归。每轮递归中,利用depth记录层数,当进入新的一层时,创建新的子容器。

//递归法
class Solution {
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth)
    {
        if (cur == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());//添加子容器
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};

107. 二叉树的层序遍历 II

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

image.png

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

示例 2:

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

示例 3:

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

思考:

本题与102. 二叉树的层序遍历类似,只需在102题的基础上,对最后的result数组进行翻转操作即可。

代码:

#include <iostream>
#include<vector>
#include<queue>

using namespace std;


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>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty())
        {
            vector<int> childvector;//子容器,储存每一层遍历的结果
            int size = que.size();//记录队列当前大小
            for (int i = 0; i < size; i++)
            {
                TreeNode* cur = que.front();
                que.pop();

                if (cur->left)
                {
                    que.push(cur->left);
                }
                if (cur->right)
                {
                    que.push(cur->right);
                }
                childvector.push_back(cur->val);
            }
            result.push_back(childvector);
        }
        return result;
    }
};

199. 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

image.png

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

示例 2:

输入: [1,null,3]
输出: [1,3]

示例 3:

输入: []
输出: []

思考:

本题仍然是一道经典的层序遍历二叉树的题,题意要求只输出最右侧的结点,所以我们只需要在每层for循环中加以判断,只输出目标结点即可。

代码:

#include <iostream>
#include<vector>
#include<queue>

using namespace std;


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> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<int> result;
        while (!que.empty())
        {
            vector<int> childvector;//子容器,储存每一层遍历的结果
            int size = que.size();//记录队列当前大小
            for (int i = 0; i < size; i++)
            {
                TreeNode* cur = que.front();
                que.pop();

                if (cur->left)
                {
                    que.push(cur->left);
                }
                if (cur->right)
                {
                    que.push(cur->right);
                }
                if (i == (size - 1))
                {
                    result.push_back(cur->val);//只输出最后一个结点
                }
       
            }
        }
        return result;
    }
};

637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

示例 1:

image.png

输入:root = [3,9,20,null,null,15,7]
输出:[3.00000,14.50000,11.00000]
解释:第 0 层的平均值为 3,第 1 层的平均值为 14.5,第 2 层的平均值为 11 。
因此返回 [3, 14.5, 11] 。

示例 2:

image.png

输入:root = [3,9,20,15,7]
输出:[3.00000,14.50000,11.00000]

提示:

  • 树中节点数量在 [1, 104] 范围内
  • -231 <= Node.val <= 231 - 1

思考:

本题的本质其实还是二叉树的层序遍历,区别在于在遍历完成后,要求取每一层的平均值,并进行输出。

代码:

值得注意的是,这里需要返回的值时double类型的。

#include <iostream>
#include<vector>
#include<queue>

using namespace std;


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<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<double> result;
        while (!que.empty())
        {
            double sum = 0;//记录每一层的和
            int size = que.size();//记录队列当前大小
            for (int i = 0; i < size; i++)
            {
                TreeNode* cur = que.front();
                que.pop();

                if (cur->left)
                {
                    que.push(cur->left);
                }
                if (cur->right)
                {
                    que.push(cur->right);
                }
                sum += cur->val;
                
            }
            result.push_back(sum/size);
        }
        return result;
    }
};

429. N 叉树的层序遍历

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

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

示例 1:

image.png

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

示例 2:

image.png

输入: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, 10^4] 之间

思考:

本题又是一道层序遍历题,但这一次的树不再是二叉树,而是一棵N叉树,每个节点都有可能有多个儿子,而不是像二叉树只含有左右结点,这就要求我们呢在遍历时做出一些调整。

代码:

在进行子儿子遍历时,再采取一层for循环,能够完成完整的遍历。

#include <iostream>
#include<vector>
#include<queue>

using namespace std;


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) {
        queue<Node*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty())
        {
            vector<int> childvector;//子容器,储存每一层遍历的结果
            int size = que.size();//记录队列当前大小
            for (int i = 0; i < size; i++)
            {
                Node* cur = que.front();
                que.pop();
                for (int i = 0; i < cur->children.size(); i++)
                {
                    if(cur->children[i])
                        {
                            que.push(cur->children[i]);
                        }
                }
                childvector.push_back(cur->val);
            }
            result.push_back(childvector);
        }
        return result;
    }
};

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

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

示例1:

image.png

输入: 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

思考

本题所考察的仍然是二叉树的层序遍历,只需要在每一层遍历时找出最大值即可。

代码:

#include <iostream>
#include<vector>
#include<queue>

using namespace std;


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) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<int> result;
        while (!que.empty())
        {
            int size = que.size();//记录队列当前大小
            int max= INT_MIN;//初始化每一层的最大值
            for (int i = 0; i < size; i++)
            {
                TreeNode* cur = que.front();
                que.pop();

                if (cur->left)
                {
                    que.push(cur->left);
                }
                if (cur->right)
                {
                    que.push(cur->right);
                }
                max = cur->val > max ? cur->val:max;//更新最大值
            }
            result.push_back(max);
        }
        return result;
    }
};

116. 填充每个节点的下一个右侧节点指针

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

示例 1:

image.png

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

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

提示:

  • 树中节点的数量在 [0, 212 - 1] 范围内
  • -1000 <= node.val <= 1000

思考:

本题的题意比较难懂,其实就是在每一层的层次遍历时记录下本层的头结点,并且在遍历时让前一个结点指向该结点即可。

代码:

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            // vector<int> vec;
            Node* nodePre;
            Node* node;
            for (int i = 0; i < size; i++) {
                if (i == 0) {
                    nodePre = que.front(); // 取出一层的头结点
                    que.pop();
                    node = nodePre;
                }
                else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node; // 本层前一个节点next指向本节点
                    nodePre = nodePre->next;
                }
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; // 本层最后一个节点指向NULL
        }
        return root;
    }
};

(117题也完全可以使用以上代码,以上的求解过程与是否为完美二叉树并没有关系)

参考:代码随想录

往期回顾:
LeetCode102. 二叉树的层序遍历
LeetCode144、145、94. 二叉树遍历
LeetCode18. 四数之和
LeetCode15. 三数之和
LeetCode383. 赎金信
LeetCode454. 四数相加 II
LeetCode1. 两数之和
LeetCode202. 快乐数
LeetCode350. 两个数组的交集 II
LeetCode349. 两个数组的交集
LeetCode1002. 查找共用字符

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

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

相关文章

【Labivew】简易计算器

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

Secure CRT远程连接很快断线问题

问题描述 我们使用Secure CRT连接远程主机时可能会遇到几分钟没操作就无法操作了&#xff0c;需要断开重新连接&#xff0c;非常的麻烦&#xff0c;假如客户端或者服务端能够在快要超时的时候给对方发送一个心跳&#xff0c;得到对方响应就重置下超时时间&#xff0c;这样就能…

arm架构 --- 中断

ARM的异常 终止程序的正常执行过程而不得不去完成的一些特殊工作 中断是异常的一种&#xff0c;包括外部硬件产生的异常和芯片内部硬件产生的内部中断。 ARM有七种处理器模式&#xff0c;其中用户模式和系统模式之外的5钟处理器模式叫做异常模式&#xff0c;用户模式之外的6…

osgEarth示例分析——osgearth_terrainprofile

前言 osgearth_terrainprofile示例&#xff0c;涉及到一个新的类 TerrainProfileCalculator(地形轮廓计算器类)&#xff0c;用来计算两个点连线之间的地形数据。左下角会根据点击的起点和终点进行计算&#xff0c;并更新显示地形信息。 效果 拖动地球&#xff0c;到某一个视…

[附源码]Python计算机毕业设计SSM基于的智慧校园安防综合管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件安全测试-Web安全测试详解-XSS攻击

目录 1. XSS攻击 1.1 XSS攻击原理 1.2 XSS能做什么 1.3 XSS三种类型 1.4 XSS三种途径 1.5 XSS测试方法 1.5.1 查看代码 1.5.2 准备测试脚本 1.5.3 自动化测试XSS漏洞 1.5.4 XSS注入常用语句 1.6 XSS漏洞防范h3 1.6.1 对输入和URL参数进行过滤(白名单和黑名单) 1.6.…

tensorflow入门(一) 计算图、张量、会话的概念

1、计算图 计算图是tensorflow中最基本的一个概念&#xff0c;tensorflow中的所有计算都被转化成计算图上的节点。tensorflow的名字已经说明了它最重要的两个概念------tensor和flow。张量这个概念在数学或者物理学中可以有不同的解释&#xff0c;在tensorflow中&#xff0c;张…

基于tensorflow的深层神经网络(三)如何用tensorflow优化神经网络

1、神经网络优化算法 梯度下降算法主要用户优化单个参数的取值&#xff0c;而反向传播算法给出了一个高效的方式在所有参数上使用梯度下降算法&#xff0c;从而使神经网络模型在训练数据上的损失函数尽可能小。反向传播算法是训练神经网络的核心算法&#xff0c;它可以根据定义…

红黑树的插入过程

一棵红黑树是一种特殊的二叉查找树&#xff0c;具有以下性质&#xff1a; 每个节点要么是红色&#xff0c;要么是黑色。根节点是黑色。每个叶子节点&#xff08;NIL&#xff09;是黑色。如果一个节点是红色的&#xff0c;那么它的两个儿子都是黑色的。从任意一个节点到其每个叶…

71.qt quick-可伸展菜单-抽屉栏示例 通用QML界面(一键换肤)

在我们之前章节已经提供过了抽屉栏和菜单伸展栏: 63.qt quick-QML侧边滑动栏(不需要任何图片资源,支持自定义左右方向和大小)_诺谦的博客-CSDN博客_qml侧边栏68.qt quick-qml多级折叠下拉导航菜单 支持动态添加/卸载 支持qml/widget加载等_诺谦的博客-CSDN博客_qml下拉菜单 由…

三维家发生工商变更:注册资本减少46%,美凯龙、阿里等股东退出

近日&#xff0c;云工业软件服务商广东三维家信息科技有限公司&#xff08;下称“三维家”&#xff09;发生工商变更&#xff0c;注册资本由16.9254亿元变更为9亿元&#xff0c;同比减少46.83%。同时&#xff0c;包括红星美凯龙、阿里巴巴等多名股东退出&#xff0c;变更时间为…

01.Spring源码整体脉络介绍及源码编译——四

IOC是核心 IOC 容器加载过程【重要】&#xff1a;所有模块都依赖IOC&#xff0c;aop&#xff0c;循环依赖都依赖IOC IOC控制反转&#xff0c;控制理念&#xff0c;来解决层与层之间的耦合。DI注入实现 怎么讲Bean交给IOC容器来管理 配置类xml&#xff0c;注解 加载spring上下…

java计算机毕业设计ssm学院校友信息管理系统的设计与实现5yqhy(附源码、数据库)

java计算机毕业设计ssm学院校友信息管理系统的设计与实现5yqhy&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts…

【Java基础篇】基础知识易错集锦(二)

我们同样用几道例题来回顾相对应的基础知识&#xff1b; 解析&#xff1a; 首先我呢区分一下实例变量和局部变量&#xff1b; 局部变量&#xff1a;定义在方法内部的变量&#xff1b;实例变量&#xff1a;定义在类中但在任何方法之外&#xff0c;你也可以理解为全局变量&…

16.C预处理器和C库

文章目录C预处理器和C库16.1翻译程序的第一步16.2明示常量&#xff1a;#define16.3在#define中使用参数16.3.1用宏参数创建字符串&#xff1a;#运算符16.3.2预处理器黏合剂&#xff1a;##运算符16.3.3变参宏&#xff1a;...和__VA_ARGS__16.4宏和函数的选择16.5文件包含&#x…

NCTF2022 calc题目复现

calc&#xff08;环境变量注入getshell&#xff09; 经典计算器题目&#xff0c;看着有点眼熟&#xff0c;没错&#xff0c;就是buu三月赛的一道题目。由于那时候web可能都算不上入门&#xff0c;所以也就没有复现。比赛时就网上看了看三月赛的wp&#xff0c;但是没有什么用&a…

IEEE 二进制浮点数的表示

今天&#xff0c;我来将 IEEE 二进制浮点数的表示方式进行一个简单的介绍。 浮点数 在 C 语言中&#xff0c;有两种存储浮点数的方式&#xff0c;分别是 float 和 double &#xff0c;当然了还有long double。这几种浮点型所容纳的长度不同&#xff0c;当然它们存储的精度也就…

[附源码]JAVA毕业设计新型药物临床信息管理系统(系统+LW)

[附源码]JAVA毕业设计新型药物临床信息管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 …

p5.第一章 Python基础入门 -- 运算符、优先级和表达式 (五)

1.2.3.2.11 False等价 False等价布尔值,相当于bool(value) 空容器 空集合set空字典dict空列表list空元组tuple空字符串None0# bool(value)是布尔函数# In: bool(1), bool(0) # Out: (True

离散数学·支配集、覆盖集、独立集和匹配

支配集 简而言之——V-支配集后剩下的点&#xff0c;都能在支配集中找到相邻的点 支配数的符号是γ0&#xff08;有关点的集&#xff0c;下标为0&#xff09; 例 右下角相同颜色的为同一个支配集 要注意极小性 整个V就是支配集&#xff08;所以说支配集找极大没有意义&#xf…