「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」
前言
二叉树的前序遍历我们已经练过了,那么今天N叉树的前序遍历理解起来就较为容易了,同样,递归法和迭代法我们都会使用。
题目描述
589. N 叉树的前序遍历
给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 。
n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。
示例 1:
输入:root = [1,null,3,2,4,null,5,6]
输出:[1,3,5,6,2,4]
解题思路
同样,题目给我们n叉树的根节点,每组节点由null值分隔,节点的子节点放在children指针指向的内存中,我们来看下children里节点的格式,其实children就是一个节点数组
有了前道题二叉树的前序遍历的基础,我们来整理n叉树前序遍历的解题思路:
递归法思路:
N叉树与二叉树的区别在于,N叉树的子节点是在children数组里,我们在写递归转换函数的时候,push完根节点后不再是对左右节点进行转换,而是要遍历children数组,每遍历一次对当前遍历节点转换一次
注意:我们这里是递归调用,每次调用都会往结果数组里添加节点值,而不是以往的深度优先执行
迭代法思路:
和二叉树类似,我们同样需要两个数组来存我们的操作节点及存储结果,不同的有两点:
- 我们需要从节点栈的栈首开始操作节点,因为
N叉树的最左边的节点是在children数组的第一项,我们需要从前往后取节点然后把节点的值放到结果数组中 - 处理子节点的时候,我们要
把子节点的children合并到操作栈的栈首,这样下一次就是操作它的子节点了。
开始解题
递归法解题:
var preorder = function(root) {
if(!root) return [];
let resArr = [];
transfer(root,resArr);
return resArr;
};
var transfer = function(root, resArr) {
if(!root) return null;
resArr.push(root.val);
if(root.children.length) { // 如果当前节点有子节点,我们就按顺序遍历操作children节点数组即可,即前序遍历
for(node of root.children) { // 遍历子节点数组中子节点
transfer(node,resArr); // 依次进行转换,最左边的节点先发起递归先进行节点操作
}
}
}
迭代法解题:
var preorder = function(root) {
if(!root) return [];
let stack = [root]; // 操作节点栈
let resArr = [];
while(stack.length) {
const node = stack.shift(); // 每次取队首的节点
resArr.push(node.val);
if(node.children.length) { // 判断当前子节点数组有没有值
stack = node.children.concat(stack); // 把子节点合并到队首,当前节点遍历操作之后就是从对首取出并操作它的子节点
}
}
return resArr;
};