「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
题目介绍
给你二叉树的根节点 root
,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
示例1
输入: root = [3,9,20,null,null,15,7]
输出: [[3],[20,9],[15,7]]
示例2
输入: root = [1]
输出: [[1]]
示例3
输入: root = []
输出: []
提示:
- 树中节点数目在范围
[0, 2000]
内 -100 <= Node.val <= 100
解题思路
本文将讲解此题的两种解题思路
思路一
第一种解题思路是利用深度优先的方法,先遍历完整棵树,并将每一层的节点从左到右放在最终结果数组的相应位置,然后对于奇数层的节点数组进行翻转,而偶数层的数组则保持原来从左到右的位置不变
解题步骤
- 判断如果这棵树是空树,则直接返回
[]
- 定义存放最后结果的数组
ans
,定义表示每一层层数的变量k
- 如果结果数组
ans
在当前层数的下标位置为undefined
,那么将[]
放置到当前下标对应的位置上 - 否则将当前节点的值
push
到与当前层数一致的下标的数组中 - 如果当前节点有孩子节点,则对其孩子节点执行
3-4
的操作,并将当前层数k + 1
传递到孩子节点的递归上,表示孩子节点所在的层数 - 重复
3-5
的操作,直到遍历完整棵树 - 此时的
ans
为每一层从左到右遍历的结果,需要将奇数层的数组进行翻转
解题代码
var zigzagLevelOrder = function(root) {
// 如果是空树,则返回 []
if (!root) return []
// 定义存放最终结果的数组
const ans = []
// 定义表示当前层数的变量
let k = 0
_levelOrder(root, k, ans)
// 对奇数层的数组进行翻转,偶数层保持不变
return ans.map((v, i) => {
if (i % 2 === 1) {
return v.reverse()
}
return v
})
};
var _levelOrder = function(root, k, ans) {
// 如果当前位置没有值,则放置 []
if (!ans[k]) ans[k] = []
// 往当前位置的数组中插入节点的值
ans[k].push(root.val)
// 如果有左孩子则递归遍历左子树
root.left && _levelOrder(root.left, k + 1, ans)
// 如果有右孩子则递归遍历右子树
root.right && _levelOrder(root.right, k + 1, ans)
}
解法二
第二种做法是利用队列的特性,将每一层的节点依次入队到节点队列中,然后依次出队,如果当前节点有孩子节点,则将左右孩子依次入队,同时维持一个标志位,表示当前层的节点需要从左到右还是从右到左插入结果数组中
解题步骤
- 判断如果当前是一棵空树,则直接返回
[]
- 定义存放最后结果的数组
ans
,定义存放节点的数组nodeArr
,并将根节点root
先入队,定义标志位sign
,如果sign
为false
,说明当前层需要从左到右,否则则是从右到左 - 如果
nodeArr
不为空,获取当前数组的长度,即为当前层的节点个数,然后定义一个存放该层结果的数组arr
- 将该层的节点依次出队,如果标志位为
false
,则从后面压入数组,否则从前面压入数组 - 如果有左右孩子节点,则将左右孩子节点依次从后面压入
nodeArr
数组中 - 结束当前层节点的遍历之后,将标志位
sign
取反,并将当前层的结果push
到ans
中 - 重复
3-6
的步骤,直到遍历完整棵树
解题代码
var zigzagLevelOrder = function(root) {
// 如果是空树,直接返回 []
if (!root) return []
// 定义存放最后结果的数组
const ans = []
// 定义存放节点的数组
const nodeArr = [root]
// 定义标志位,false表示从左往右,true表示从右往左
let sign = false
while (nodeArr.length) {
// 获取当前层的节点数量
const len = nodeArr.length
const arr = []
for (let i = 0; i < len; i++) {
// 将当前层节点依次出队
const node = nodeArr.shift()
if (!sign) {
// 如果为false,从后面插入数组
arr.push(node.val)
} else {
// 如果为true,从前面插入数组
arr.unshift(node.val)
}
// 如果有左孩子,将左孩子插入节点数组
node.left && nodeArr.push(node.left)
// 如果有右孩子,将右孩子插入节点数组
node.right && nodeArr.push(node.right)
}
// 遍历完一层之后,改变sign的值
sign = !sign
// 将当前层的结果插入到结果数组中
ans.push(arr)
}
return ans
};