「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」
前言
每天至少一道算法题,死磕算法
看到二叉树就比较兴奋,因为《labuladong算法小抄》上说过刷题一定要先刷二叉树
那么为什么要先刷二叉树呢,因为二叉树是最容易培养框架思维的,而且大部分算法技巧,本质上都是树的遍历问题。
那么接下来一段时间我们就一起来探索二叉树的模板,多刷几道2叉树
Q:BFS和队列有什么关系?为什么BFS中常常有queue的影子?
A:
既然叫层序遍历,有时候你是不是要知道自己在第几层(好多题会这样考),那我们访问第一层,打个标记,这是第一层,访问完毕,然后第一层的数据出来,我们访问第二层,在打个标记,这是第二层,访问完毕,第二层的数据都出来,我们访问第三层...这种访问数据的结构很像队列,访问第一层,a入列,开始访问,发现a下面有b,b入列,a出列,开始访问第二层,发现b下面有三个c,d,e三个元素,那么c,d,e入列,b出列...所以这种访问的方式不就是队列么,有了队列我们可以更好的访问,更好的记录楼层
接下来开始做题
题目
给你二叉树的根节点 root ,返回其节点值的层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
思路
二叉树的题目都有框架,我们做题的时候直接套用框架就可以了,但是一定要理解,然后在记忆
先上BFS的框架
function BFS(入口坐标) {
const queue = [] // 初始化队列queue
// 入口坐标首先入队
queue.push(入口坐标)
// 入口坐标是第一层也就是0,所以level从1开始,代表遍历第二层
let level = 1;
// 队列不为空,说明没有遍历完全
while(queue.length) {
// 当前queue的长度,一定要先声明长度,因为queue一直在变
let length = queue.length;
// for循环使当前层的都出列,下一层的都入列
for(let i=0;i<length;i++){
// 上面的i不要用,因为我们
let node = queue.shift();
// 从node上取出元素,放到queue队列中
queue.push(取出的元素)
}
// 层数+1;
level++;
}
}
有了框架,我们写起来直接套框架就可以啦
var levelOrder = function(root) {
// 如果入口是空的,那么直接返回空数组,无论是字符串,数组,链表,二叉树,首先要考虑为空的情况
if(!root){
return [];
}
// 初始化队列
let queue = [];
// 入口文件入列
queue.push(root);
// 要返回的结果,就是把每一层的数值以一个数组的形式返回
// 第一个数组就是第一层的值
let result = [[root.val]];
// 定义楼层
let level = 1;
// 开始遍历队列中的数据
while(queue.length){
// 当前楼层的长度
let length = queue.length;
// 初始化当前楼层数组
result[level] = [];
// 遍历当前楼层元素
for(let i=0;i<length;i++){
// 取出元素
let node = queue.shift();
// 访问左侧元素
if(node.left){
// 存入当前楼层数值
result[level].push(node.left.val);
// 添加元素入队列
queue.push(node.left);
}
// 访问右侧元素
if(node.right){
// 存入当前楼层数值
result[level].push(node.right.val);
// 添加元素入队列
queue.push(node.right);
}
}
// 如果当前楼层是空楼层,那么这层楼就不要了,是为了处理最后一层
if(!result[level].length){
result.pop();
}
// 访问下一层
level++;
}
return result;
};
总结
掌握了层序遍历,那可了不得,二叉树的大门正在慢慢向你敞开