开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
- 二叉树的层序遍历
- 107.二叉树的层序遍历 II
- 二叉树的右视图
- 二叉树的层平均值
层序遍历
什么是层序遍历?先来看看例子
给你一个二叉树,[3,9,20,null,null,15,7]
让你输出 !
知道二叉树的层序遍历,可以一口气打完以下十题:
102.二叉树的层序遍历
题目链接:102. 二叉树的层序遍历
遍历思路:借助队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
- 首先遍历第一层的节点,记录根节点的val,然后放入队列中,同时记录队列的length。
- 弹出根节点,然后依次将上述根节点的左节点val 、右节点val 放入队列中
- 只有队列的length为0时,才开始遍历下一层
var levelOrder = function(root) {
//二叉树的层序遍历
let res = [], queue = []; // res存放结果,queue是咱们借助的队列
queue.push(root);
if(root === null) {
return res;
}
while(queue.length !== 0) {
// 记录当前层级节点数
let length = queue.length;
//存放每一层的节点
let curLevel = [];
for(let i = 0; i < length; i++) {
let node = queue.shift();
curLevel.push(node.val);
// 存放当前层下一层的节点
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
//把每一层的结果放到结果数组
res.push(curLevel);
}
return res;
};
拿测试用例 root = [3,9,20,null,null,15,7] 来解释一些问题
- 函数里面第二行
queue.push(root);解读:执行完这一句话, queue 的值变为[ [3,9,20,null,null,15,7] ];queue的长度为1 。 - 第一次执行
let node = queue.shift();后, node 为 [3,9,20,null,null,15,7] ,此时queue的长度为 0。这个就是弹出每一层根节点的操作。 curLevel.push(node.val);第一次进行这个操作后,curLevel 的值为 [3] ,后续把 curLevel push进 res 后,res 就是一个二维数组。- 当node的左右子节点存在时,就放到队列中。补充一点,只要“&&”前面是true,无论“&&”后面是true还是false,结果都将返“&&”后面的值;只要“&&”前面是false,无论“&&”后面是true还是false,结果都将返“&&”前面的值。总结:假前真后!
for 循环的作用?因为我们知道了每次存入数据后,queue中的长度,就相当于每一层节点的个数。拿本例子来说,第一次根节点为 3 ,queue 的 length为 1 。当存放当前层下一层的节点后,queue 里面就有了两个元素。那么下次再进行 while 循环的时候就能知道这一层有多少节点。
107.二叉树的层次遍历II
题目链接:107. 二叉树的层序遍历 II
给你二叉树的根节点
root,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)输入:root = [3,9,20,null,null,15,7] 输出:[[15,7],[9,20],[3]]
思路:相对于102.二叉树的层序遍历,就是最后把result数组反转一下就可以了。
代码:根据上一题的代码,修改部分语句
// 方法一:返回res的时候直接反转
return res.reverse();
// 方法二:在执行完for循环后,curLevel压入res时,从数组前头插入值,避免最后反转耽误更多时间
res.unshift(curLevel);
199.二叉树的右视图
题目链接:199. 二叉树的右视图 - 力扣(LeetCode)
给定一个二叉树的 根节点
root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
思路:我想的是在存入下一层的节点时,仅仅存右节点的。但是出现了问题。当测试用例为 [1,2] 时,期望输出 [1, 2] 。实际输出 [1]
问题就在于,题目不是想找右节点,而是从右边能看到的第一个节点。不一定限制左右子节点。
按照卡神的说法,“层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。”
代码:
var rightSideView = function (root) {
let res = [], queue = [];
queue.push(root);
while (queue.length && root !== null) {
// 记录当前层级节点个数
let length = queue.length;
while (length--) {
let node = queue.shift();
//length长度为0的时候表明到了层级最后一个节点
if (!length) {
res.push(node.val);
}
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return res;
};
所以,应该这样考虑:
- 首先不需要在再定义一个 curLevel 了。
- 不过还是需要设置一个
length来记录节点的个数。 - node 还是接住 queue 弹出来的数,那在这种不断while的过程中就能把一个个节点值放到queue里面
- 当 queue 长度为 0 的时候,就说明到了这一层最后一个节点了,就是我们要求的值,压入 res 即可。
637.二叉树的层平均值
题目链接:637. 二叉树的层平均值 - 力扣(LeetCode)
给定一个非空二叉树的根节点
root, 以数组的形式返回每一层节点的平均值。与实际答案相差10-5以内的答案可以被接受。输入: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]
思路:在层序遍历的时候把一层求个总和在取一个均值。
代码:
var averageOfLevels = function (root) {
//层级平均值
let res=[],queue=[];
queue.push(root);
while(queue.length&&root!==null){
//每一层节点个数
let length=queue.length;
//sum记录每一层的和
let sum=0;
for(let i=0;i<length;i++){
let node=queue.shift();
sum+=node.val;
node.left&&queue.push(node.left);
node.right&&queue.push(node.right);
}
//每一层的平均值存入数组res
res.push(sum/length);
}
return res;
};
参考文章:
- JS构造二叉树一只哆啦呀的博客-CSDN博客js构建二叉树
- js通过数组创建二叉树Maximus_ckp的博客-CSDN博客js 创建一个二叉树
- ES6模块导入导出(export&&export default等)总结 - 掘金 (juejin.cn)
- JavaScript 模块导入导出 - 知乎 (zhihu.com)
- (1条消息) JS中的 || 与 && 运算符详解I am Joey.的博客-CSDN博客js中||
有些文章是在本地debug的时候遇到了一些问题,去查完相关文章以后,放在这里供后期复习。