

文章目录
摘要
这道题其实非常"树的基本功"。我们要对一棵 N 叉树(每个节点可以有任意数量的子节点) 做层序遍历,也就是 BFS,从上到下、一层一层扫过去,最后输出成一个二维数组。
虽然思路很基础,但在实际项目里,也经常会遇到需要按层处理节点的情况,比如:
- UI 结构的按层遍历(菜单、组件树)
- 配置树按层读取
- 文件结构扫描
- 大模型 Prompt Tree 的逐级展开
所以,除了 LeetCode,本题本质是一类通用场景,非常值得系统掌握。
下面我们会从题目、代码实现、细节解析、示例运行等角度,带你把这个 BFS 方案拆得明明白白。

描述
题目给你一棵 N 叉树,让你输出它的层序遍历结果。
也就是:
- 第一层:树根
- 第二层:树根的所有子节点
- 第三层:第二层所有节点的子节点
- 依此类推
输入是按层序序列化格式给的,比如:
txt
[1,null,3,2,4,null,5,6]
null 表示"这一层的子节点结束"。
因为我们写 Swift,所以要自己定义 Node 结构:
swift
public class Node {
public var val: Int
public var children: [Node]
public init(_ val: Int) {
self.val = val
self.children = []
}
}
我们的任务很直接:返回一个二维数组,每一层就是一行。
题解答案
核心思路就是 广度优先搜索(BFS)。
步骤非常固定:
-
判断 root 是否为空,是则返回空数组。
-
准备一个队列,把 root 放进去。
-
每次循环处理一层:
- 记录当前队列的长度(这一层节点的数量)
- 逐个弹出节点,把 node.val 放入这一层的数组
- 把它的 children 全部加入队列
-
直到队列为空,遍历结束。
最终输出所有层的结果。

题解代码分析
下面给出可直接运行的 Swift 代码,并在后面逐行解析:
swift
import Foundation
// N 叉树节点定义
public class Node {
public var val: Int
public var children: [Node]
public init(_ val: Int) {
self.val = val
self.children = []
}
}
// 层序遍历实现
class Solution {
func levelOrder(_ root: Node?) -> [[Int]] {
guard let root = root else { return [] }
var result: [[Int]] = []
var queue: [Node] = [root]
while !queue.isEmpty {
let size = queue.count
var level: [Int] = []
for _ in 0..<size {
let node = queue.removeFirst()
level.append(node.val)
for child in node.children {
queue.append(child)
}
}
result.append(level)
}
return result
}
}
代码拆解说明
1. 根节点判空
swift
guard let root = root else { return [] }
非常常见的防御式编程,避免 root 为 nil 导致后续逻辑无法执行。
2. 用数组模拟队列
swift
var queue: [Node] = [root]
Swift 标准库没有官方 Queue,所以我们用数组加 removeFirst() 来模拟。虽然复杂度不是最优,但是在这里完全够用。
如果你真的遇到性能极端要求,可以用自己实现的 Deque 结构,但 LeetCode 已经绰绰有余。
3. BFS 主体逻辑
swift
while !queue.isEmpty {
let size = queue.count
var level: [Int] = []
关键点是这行:
txt
let size = queue.count
它告诉我们"这一层一共有多少节点",防止后续入队操作影响层的边界。
4. 遍历这一层
swift
for _ in 0..<size {
let node = queue.removeFirst()
level.append(node.val)
每次从队列头部拿出一个节点,并把值存进当前层。
5. 将子节点全部入队
swift
for child in node.children {
queue.append(child)
}
N 叉树的关键就是 children 是一个数组,所以可以有不限数量的子节点。
示例测试及结果
我们来写一段可运行的 Demo 来验证逻辑。
下面构造两棵树,对照题目中的例子。
swift
func buildExampleTree1() -> Node {
let root = Node(1)
let node3 = Node(3)
let node2 = Node(2)
let node4 = Node(4)
node3.children = [Node(5), Node(6)]
root.children = [node3, node2, node4]
return root
}
let example1 = buildExampleTree1()
let sol = Solution()
print(sol.levelOrder(example1))
运行结果
txt
[[1], [3, 2, 4], [5, 6]]
完全符合示例 1。
再来一个更复杂的树示例(简化版示例 2):
swift
func buildExampleTree2() -> Node {
let root = Node(1)
let level2 = [Node(2), Node(3), Node(4), Node(5)]
root.children = level2
level2[1].children = [Node(6), Node(7)]
level2[2].children = [Node(8)]
level2[3].children = [Node(9), Node(10)]
return root
}
let example2 = buildExampleTree2()
print(sol.levelOrder(example2))
运行结果
txt
[[1], [2, 3, 4, 5], [6, 7, 8, 9, 10]]
也完全符合期望。
时间复杂度
O(N)
N 是节点总数。
每个节点都会入队 / 出队一次,并被处理一次,所以整体是线性的。
空间复杂度
O(N)
主要来自:
- 队列的存储
- 输出结果本身
在最宽的一层,队列可能临时存下大量节点。
总结
这一题的解法非常经典: BFS 层序遍历。它的难度不在算法,而在于你需不需要对 N 叉树的结构适应一下。
如果用二叉树的思路迁移过来,基本可以无缝写出来。
在实际项目里,层序遍历也非常常见,比如:
- 从 UI 结构按层级序列化
- 图结构按 level 扩展
- 树形配置批量读取
- 大模型多轮逻辑树展开
所以这道题非常值得你熟练掌握它的代码结构。