剑指Offer_#32_从上到下打印二叉树
剑指Offer_#32_从上到下打印二叉树
Contents
这一题有三个变式,题目有细微差别.
剑指Offer32-I:不分行从上到下打印二叉树
题目
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回:
[3,9,20,15,7]
提示:
节点总数 <= 1000
思路分析
这一题的遍历方式就是广度优先遍历(BFS),可以借助队列数据结构来实现。
算法流程
- 特殊情况:输入为null,直接返回空数组。
- 初始化:初始化队列
q
,将root
加入队列,初始化结果列表res
。 - while循环:
- 循环条件:队列不为空
- 循环内容:
- 取出队首元素
cur
- 将
cur
的值加入到res
- 把
cur
的左右字节点加入队列q
- 取出队首元素
- 返回结果:将
res
转换为指定的int数组类型。
解答
class Solution {
public int[] levelOrder(TreeNode root) {
if(root == null) return new int[0];
ArrayList<Integer> res= new ArrayList<>();
//注意Queue的实例化方法,右边写的是LinkedList,因为LinkedList实现了Queue接口
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
//取出队首元素
TreeNode cur = q.poll();
//取出的元素,加入到res列表
res.add(cur.val);
//继续将当前节点的左右子节点加入队列
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
//不能使用res.toArray()作为返回值,因为这样返回类型是Integer[],而非int[]
//只能for循环赋值给int[]
int[] intRes = new int[res.size()];
for(int i = 0;i <= intRes.length - 1;i++){
intRes[i] = res.get(i);
}
return intRes;
}
}
剑指Offer32-II:分行从上到下打印二叉树
题目
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
提示:
节点总数 <= 1000
思路分析
和上一题相比,多了一个分行打印的要求。
思路是,while循环当中再加入一层for循环,每个for循环打印一层的内容。
关键在于如何控制for循环刚好打印完一层节点就结束?
很巧妙的思路是:使用队列长度来初始化循环变量i,每次循环i递减。
这样正好可以把一层的节点添加完。
解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
List<Integer> tmp = new ArrayList<>();
//ERROR:这样写不行,因为q.size()每一轮都在变化,应该把q.size()作为初始化
//for(int i = 0;i <= q.size() - 1;i++){
for(int i = q.size();i > 0;i--){
TreeNode cur = q.poll();
tmp.add(cur.val);
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
res.add(tmp);
}
return res;
}
}
剑指Offer32-III:之字形从上到下打印二叉树
题目
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]
提示:
节点总数 <= 1000
思路分析
跟上一题基本一样,唯一的区别在于,需要根据层数的奇偶来控制打印顺序。只需要在向tmp
添加元素的时候,加一个条件判断即可。
解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
List<Integer> tmp = new ArrayList<>();
for(int i = q.size();i > 0;i--){
TreeNode cur = q.poll();
//相比上一题改动的地方
//当前已经打印出来的层数是偶数层,那么目前打印的是奇数层,应该按照从左到右的顺序
if(res.size() % 2 == 0) tmp.add(cur.val);
//当前已经打印出来的层数是奇数层,那么目前打印的是偶数层,应该按照从右到左的顺序
else tmp.add(0,cur.val);
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
res.add(tmp);
}
return res;
}
}