Easy | LeetCode 102 | 剑指 Offer 32 - II. 从上到下打印二叉树 II | 二叉树层次遍历
剑指 Offer 32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
提示:
节点总数 <= 1000
方法一: 双队列
使用两个队列实现, 一个队列用于遍历本层的节点, 另一个队列用于存放下一层的节点。
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) {
return res;
}
// 定义两个队列, 分别用于遍历本层的节点 和 存放 下一层的节点
Deque<TreeNode> queue1 = new ArrayDeque<TreeNode>();
Deque<TreeNode> queue2 = new ArrayDeque<TreeNode>();
queue1.addLast(root);
// 只要有队列非空就要继续遍历
while (!queue1.isEmpty() || !queue2.isEmpty()) {
// 用于存放本层的结果
List<Integer> curRes = new ArrayList<>();
while (!queue1.isEmpty()) {
// 将队列1的元素逐个出队
TreeNode node = queue1.removeFirst();
curRes.add(node.val);
if (node.left != null) {
// 将出队元素的左右孩子入队到队列2
queue2.addLast(node.left);
}
if (node.right != null) {
queue2.addLast(node.right);
}
}
if (curRes.size() > 0) {
res.add(curRes);
}
// 用于放置本层遍历的结果
curRes = new ArrayList<>();
// 如果队列2有元素 就将其出队遍历
while (!queue2.isEmpty()) {
TreeNode node = queue2.removeFirst();
curRes.add(node.val);
if (node.left != null) {
// 将其孩子添加对另个一队列 队列1
queue1.addLast(node.left);
}
if (node.right != null) {
queue1.addLast(node.right);
}
}
// 在这里CurRes是有可能没有元素的, 因为上次队列1的元素可能就是数的最后一层
if (curRes.size() > 0) {
res.add(curRes);
}
}
return res;
}
方法二
可以只使用一个队列, 通过统计每层元素的个数来实现对各个层的控制
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
if(root != null) queue.add(root);
while(!queue.isEmpty()) {
List<Integer> tmp = new ArrayList<>();
// 在while的每一轮循环开始的时间, 计算队列的大小
// 这个大小就是本层元素的个数
// 在这里先对本层所有元素出队, 同时将其孩子入队
for(int i = queue.size(); i > 0; i--) {
TreeNode node = queue.poll();
tmp.add(node.val);
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
// for循环结束之后, 队列的元素就恰好是下一层的所有元素
res.add(tmp);
}
return res;
}