LeetCode刷题复盘笔记:我要打六个——打爆二叉树(层序遍历,右视图,层平均值、最大值)

我要打六个——打爆层序遍历

在此非常感谢“代码随想录”的通俗易懂的总结,直接感觉打通层序遍历的任督二脉,可以一口气打六个!

(致敬叶师傅和李小龙)

在这里插入图片描述

“我不害怕曾经练过一万种踢法的人,但我害怕一种踢法练过一万次的人”(by 叶师傅的徒弟Bruce Lee)
在这里插入图片描述

今天是2021年3月14日,在这个龙抬头和白色情人节的“双节”日子里,第一次一口气刷了6道中等难度Leetcode题(主要是层序遍历),一个字——,加油,冲冲冲!

一、总体思路:

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们最常见的前中后序遍历都不太一样。
需要借用一个辅助数据结构即队列来实现,「队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
「而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。」

二、具体题目

题目1:102. 二叉树的层序遍历

题目描述:
给你一个二叉树,请你返回其按层序遍历得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
在这里插入图片描述

C++代码

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();  // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            vector<int> vec;
            for(int i=0;i<size;++i){
                TreeNode* cur=que.front();
                que.pop();
                if(cur) vec.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

题目2:107. 二叉树的层序遍历 II

题目描述:
给定一个二叉树,返回其节点值自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树 [3,9,20,null,null,15,7]
在这里插入图片描述

C++代码:

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();
            vector<int> vec;
            for(int i=0;i<size;++i){
                TreeNode* cur=que.front();
                que.pop();
                if(cur) vec.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

题目3:199. 二叉树的右视图

题目描述:
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
在这里插入图片描述

C++代码:

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;++i){
                TreeNode* cur=que.front();
                que.pop();
                if((i==size-1) && (cur)) result.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return result;
    }
};

题目4:637. 二叉树的层平均值

题目描述:
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
示例:
在这里插入图片描述

C++代码:

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> que;
        vector<double> result;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();
            double levelsum=0.0;
            for(int i=0;i<size;++i){
                TreeNode* cur=que.front();
                que.pop();
                if(cur) levelsum+=cur->val;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(levelsum/size);
        }
        return result;
    }
};

题目5:429. 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]]

C++代码:

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> que;
        vector<vector<int>> result;
        if(root) que.push(root);
        while(!que.empty()){
            int size=que.size();  // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            vector<int> vec;
            for(int i=0;i<size;++i){
                Node* cur=que.front();
                que.pop();
                if(cur) vec.push_back(cur->val);
                    for(int j=0;j<cur->children.size();++j){
                        if(cur->children[j]){
                            que.push(cur->children[j]);
                    }               
                }              
            }
            result.push_back(vec);
        }
        return result;
    }
};

题目6:515. 在每个树行中找最大值

题目描述:
您需要在二叉树的每一行中找到最大的值。
示例:
在这里插入图片描述

C++代码:

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        if(root) que.push(root);
        vector<int> result;
        while(!que.empty()){
            int size=que.size();
            int levelmax=que.front()->val;
            // int levelmax=INT_MIN;
            for(int i=0;i<size;++i){
                TreeNode* cur=que.front();
                que.pop();
                if(cur->val>levelmax) levelmax=cur->val;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(levelmax);
        }
        return result;
    }
};

总结

二叉树
前中后序遍历统称为——深度优先遍历
层序遍历即为——广度优先遍历

二叉树的层序遍历,就是图论中的广度优先搜索在二叉树中的应用,需要借助队列来实现(队列的应用)。
学会二叉树的层序遍历,可以一口气做完Leetcode上六道题目:
102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
589.N叉树的前序遍历
515.在每个树行中找最大值

思维:对于层序遍历要直接想起队列方法!

层序遍历只要掌握基本写法(也就是框架模板),剩下的就是在二叉树每一行遍历的时候做做逻辑修改。

Notes:
1.对于N叉树,children是一个类似于节点Node列表的东西,需要循环children.size()次迭代children[i]入队!

2.之后求最大值直接把max初始化为INT_MIN,求最小值时直接把min初始化为INT_MAX,这样就会避免最后输出值为最开始初始化的0值

INT_MIN在标准头文件limits.h中定义。

#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
在C/C++语言中,不能够直接使用-2147483648来代替最小负数,因为这不是一个数字,而是一个表达式。表达式的意思是对整数21473648取负,但是2147483648已经溢出了int的上限,所以定义为(-INT_MAX -1)

C中int类型是32位的,范围是-2147483648到2147483647
(1)最轻微的上溢是INT_MAX + 1 :结果是 INT_MIN
(2)最严重的上溢是INT_MAX + INT_MAX :结果是-2
(3)最轻微的下溢是INT_MIN - 1:结果是是INT_MAX
(4)最严重的下溢是INT_MIN + INT_MIN:结果是0


欢迎大家扫码关注本人公众号:编程复盘与思考随笔

(关注后可以免费获得本人在csdn发布的资源源码)

公众号主要记录编程和刷题时的总结复盘笔记和心得!并且分享读书、工作、生活中的一些思考感悟!在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Al资料站与复盘笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值