发布于 

剑指Offer.32-从上到下打印二叉树

剑指Offer.32-从上到下打印二叉树

方法一:层序遍历 + 偶数层直接逆序

亮点

  • 仅使用链表一种数据结构即可,无需额外引入别的数据结构
  • 仅对偶数层做反转即可

题解

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
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
// 广度优先搜索实现层序遍历
// 与常规层序遍历不同的地方在于 此次出队时需要按层出队
int flag = 0;
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new LinkedList<>();
//合法性检验
if (root == null){
return res;
}
queue.offer(root);
while(!queue.isEmpty()){
//获取当前队列的大小
int queueSize = queue.size();
LinkedList<Integer> subRes = new LinkedList<>();
for(int i=0;i<queueSize;i++){
TreeNode t = queue.poll();
subRes.add(t.val);
if(t.left != null){
queue.add(t.left);
}
if(t.right != null){
queue.add(t.right);
}
}
//判断当前层数是奇数层还是偶数层,当为奇数层的时,存储反转的结果
if(flag % 2 == 1){
Collections.reverse(subRes);
res.add(subRes);
}else{
res.add(subRes);
}
flag++;
}
return res;
}
}

注意点

反转LinkedList,使用的方法为Collections.reverse()方法

方法二:利用双端队列的特性,反向存储

亮点

  • 引入双端队列,通过双端队列的特性实现层逆序

题解

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
35
36
37
38
39
40
41
42
43
44
45
46
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
// 广度优先搜索实现层序遍历
// 与常规层序遍历不同的地方在于 此次出队时需要按层出队
int flag = 0;
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new LinkedList<>();
//合法性检验
if (root == null){
return res;
}
queue.offer(root);
while(!queue.isEmpty()){
//获取当前队列的大小
int queueSize = queue.size();
LinkedList<Integer> subRes = new LinkedList<>();
for(int i=0;i<queueSize;i++){
TreeNode t = queue.poll();
//按照当前层的奇偶决定其插入位置
if(flag % 2 == 1){
subRes.addFirst(t.val);
}else{
subRes.addLast(t.val);
}
if(t.left != null){
queue.add(t.left);
}
if(t.right != null){
queue.add(t.right);
}
}
flag++;
res.add(subRes);
}
return res;
}
}

方法三:奇偶层处理逻辑剥离

亮点

  • 减少了每次插入元素的判断过程

题解

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) {
Deque<TreeNode> deque = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
// 由于根节点的数量必定为1 故从左侧或右侧插入无需区分
if(root != null) deque.add(root);
while(!deque.isEmpty()) {
// 打印奇数层
List<Integer> tmp = new ArrayList<>();
for(int i = deque.size(); i > 0; i--) {
// 从左向右打印
TreeNode node = deque.removeFirst();
tmp.add(node.val);
// 先左后右加入下层节点
if(node.left != null) deque.addLast(node.left);
if(node.right != null) deque.addLast(node.right);
}
res.add(tmp);
if(deque.isEmpty()) break; // 若为空则提前跳出
// 打印偶数层
tmp = new ArrayList<>();
for(int i = deque.size(); i > 0; i--) {
// 从右向左打印
TreeNode node = deque.removeLast();
tmp.add(node.val);
// 先右后左加入下层节点
if(node.right != null) deque.addFirst(node.right);
if(node.left != null) deque.addFirst(node.left);
}
res.add(tmp);
}
return res;
}
}

注意点

  • 奇数层偶数层之间需要增加一层判断,当队中无元素需要退出循环

执行过程

记录单节点3后,下一层的入队操作

First Last
null 9,20

偶数层遍历时,从右向左遍历,遍历顺序变为20 9,之后,执行奇数层节点入队操作

First Last
15,7 null

遍历时从First端弹出元素,因此顺序为正向15 7


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @John Doe 创建,使用 Stellar 作为主题。