(LeetCodeHot100)102. 二叉树的层序遍历——binary-tree-level-order-traversal

102. 二叉树的层序遍历——binary-tree-level-order-traversal

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

img

1
2
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

1
2
输入:root = [1]
输出:[[1]]

示例 3:

1
2
输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000

我的思路

  • 最简单的就是直接顺序输出层序遍历,但是这里要分层(每层是一个List)
  • 我想到了老师讲的哨兵结点:

我的错误代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Deque<TreeNode> queue = new LinkedList<>();
// 根节点先入队
queue.offer(root);
// 定义一个标记,方便分层
queue.offer(new TreeNode(Integer.MAX_VALUE));
while (!queue.isEmpty()) {
List<Integer> list1 = new ArrayList<>();
TreeNode p = queue.peek();
if (p.val != Integer.MAX_VALUE) {
list1.add(p.val);
}
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
queue.pop();
if (!queue.isEmpty() && queue.peek().val == Integer.MAX_VALUE) {
// 到标记了,说明该层入队结束了
ans.add(list1);
queue.pop();
queue.offer(new TreeNode(Integer.MAX_VALUE));
}
}
return ans;
}
}

顺着我的思路的代码3ms|击败2.41%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) { // 修复错误1:空根节点直接返回
return ans;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
queue.offer(new TreeNode(Integer.MAX_VALUE)); // 哨兵标记第一层结束

List<Integer> currentLevel = new ArrayList<>(); // 存储当前层元素
while (!queue.isEmpty()) {
TreeNode p = queue.poll(); // 取出队首节点(直接poll,避免重复peek)

if (p.val == Integer.MAX_VALUE) { // 遇到哨兵,说明当前层遍历结束
ans.add(new ArrayList<>(currentLevel)); // 加入结果集
currentLevel.clear(); // 清空,准备下一层
// 如果队列不为空,说明还有下一层,加新哨兵
if (!queue.isEmpty()) {
queue.offer(new TreeNode(Integer.MAX_VALUE));
}
} else { // 普通节点:取值 + 入队左右子树
currentLevel.add(p.val); // 修复错误2:收集当前层所有节点
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
}
}
return ans;
}
}

更简洁的写法1ms|击败97.34%

==(不用哨兵,统计每层节点数)==

哨兵思路可行,但统计每层节点数的写法更直观、无额外节点开销,推荐掌握:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) return ans;
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);

while (!queue.isEmpty()) {
int levelSize = queue.size(); // 关键:当前层的节点数
List<Integer> currentLevel = new ArrayList<>();
// 遍历当前层的所有节点(循环levelSize次)
for (int i = 0; i < levelSize; i++) {
TreeNode p = queue.poll();
currentLevel.add(p.val);
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
}
ans.add(currentLevel); // 当前层遍历完,加入结果
}
return ans;
}
}
  • 还是我想复杂了