「剑指Offer 32-II. 从上到下打印二叉树 II」
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
示例
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
思路分析
与剑指Offer32-1几乎一摸一样,唯一的区别就是返回的数据格式不同,根据题目要求返回List<List<Integer>>
格式。从第一题的分析中已经知道,二叉树 按层打印,也就是广度优先搜索 BFS,一般需要借助 队列 的 先入先出 的性质来实现,但是这一题要求将每一层的数字放在同一个集合List
当中,最终返回整个的集合List
。这个好办,考虑使用队列,每一层即是当前队列的长度size,但是随着队列不断执行offer
操作,队列的大小size
是动态改变的。而我们知道的是每层的数字需要被添加到一个临时的temp
集合当中,这个集合的大小与队列大小相同,这个简单一个for
循环搞定。但是这里需要倒序
进行循环,从高到低。因为队列的size不断减小,习惯从低到高遍历结果不正确,但是从高到低,由于初始的size等于每一层结合的大小,递减循环达到条件后直接退出。比采用如临时变量方法来的简单一点。思路总结:
- 二叉树为空时的处理
- 借助队列Queue将遍历到的节点存入到队列中,首先入队列的是根节点(root)
- 从左到右,添加子节点(如果存在)
- 对于每一层数字加入到集合当中,采用从高到低的循环添加方式
- 返回结果
代码实现
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if (null == root) {
return new ArrayList<>();
}
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> temp = new ArrayList<>();
/*queue的大小是变化的,因此要作为初始值作为遍历的条件*/
for (int i = queue.size(); i > 0; i--) {
TreeNode node = queue.poll();
if (null != node) {
temp.add(node.val);
if (null != node.left) {
queue.offer(node.left);
}
if (null != node.right) {
queue.offer(node.right);
}
}
}
result.add(temp);
}
return result;
}
}
比较难想到的就是从高到低去循环存入每层的数字,可能平时开发的习惯决定了,遇到for
循环这种习惯性从低到高。“经验”有时候往往也是会限制思维的扩展。
复杂度
时间复杂度O(N):需要访问二叉树所有节点
空间复杂度O(N):使用队列存储二叉树的节点,极端情况下使用 N 额外的内存空间