题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],
- 3
- / \
- 9 20
- / \
- 15 7
返回其层次遍历结果:
- [
- [3],
- [20,9],
- [15,7]
- ]
提示:
-
解法1:BFS,广度优先搜索,时间复杂度o(n),空间复杂度o(n)
创建一个队列,用于存放树,首先加入根节点
- 两次循环,在循环中,先让当前队头节点出队,然后把判断它的左右子节点是否为空,如果不为空则按左右的顺序加入队列,大循环每次代表一层,小循环代表每个节点
在每一层大循环中,需要判断当前层是否为奇数层,如果是奇数层(从0开始),则需要把临时的list倒置,再加入到结果集res中
// 翻转list,添加到res
if(level % 2 == 1){
Collections.reverse(list);
}
res.add(list);
level++;
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int level = 0;
while(!deque.isEmpty()){
int sz = deque.size();
List<Integer> list = new ArrayList<>();
for(int i = 0 ; i < sz ; i++){
TreeNode node = deque.poll();
list.add(node.val);
if(node.left != null){
deque.offer(node.left);
}
if(node.right != null){
deque.offer(node.right);
}
}
// 翻转list,添加到res
if(level % 2 == 1){
Collections.reverse(list);
}
res.add(list);
level++;
}
return res;
}
改进方式:使用一个布尔变量,少了%运算,因为从第1行开始,每一行都与上一行顺序相反
另外,如果是右往左的添加方式,则list每次把当前元素加在第0个位置即可
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int level = 0;
boolean leftToRight = true;// 是否从左到右
while(!deque.isEmpty()){
int sz = deque.size();
List<Integer> list = new ArrayList<>();
for(int i = 0 ; i < sz ; i++){
TreeNode node = deque.poll();
// 如果是正序
if(leftToRight){
list.add(node.val);
}else{
list.add(0,node.val);
}
if(node.left != null){
deque.offer(node.left);
}
if(node.right != null){
deque.offer(node.right);
}
}
res.add(list);
leftToRight = !leftToRight;
}
return res;
}
解法2:奇偶分层打印,时间复杂度o(n),空间复杂度o(n)
- 依然按照每层顺序打印
- 奇数层:各个节点顺序加入list尾部
- 偶数层:各个节点依次加入list前面
```java
class Solution {
LinkedList
- > res = new LinkedList<>();
public List
if(root == null)
return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.add(root);
boolean odd_level = true;
while(!deque.isEmpty()){
int sz = deque.size();
LinkedList<Integer> list = new LinkedList<>();
for(int i = 0 ; i < sz ; i++){
TreeNode node = deque.poll();
if(odd_level == true)
list.addLast(node.val);
else
list.addFirst(node.val);
if(node.left != null)
deque.add(node.left);
if(node.right != null)
deque.add(node.right);
}
odd_level = !odd_level;
res.addLast(list);
}
return res;
- > levelOrder(TreeNode root) {
}
}
<a name="pr2YS"></a>
## 解法3:DFS,深度优先搜索,时间复杂度O(n),空间复杂度O(n)
1. 递归的结束条件为,root == null返回
1. 递归时,需要考虑到层级和当前list的大小,如果当前层级 >= List的大小,说明已经到了下一层,需要重新new 一个list
```java
// 说明需要到下一层了
if(level >= res.size()){
res.add(new ArrayList());
}
先在对应层级添加对应元素,然后进行递归调用,需要先左再右,level层级+1,递归调用时,需要根据当前的level,如果level是奇数,则添加顺序为从左到右,否则为从右到左(每次把当前元素添加到最前面)
if((level & 1) == 0) res.get(level).add(root.val); else res.get(level).add(0,node.val); dfs(res,root.left,level+1); dfs(res,root.right,level+1);
public List<List<Integer>> levelOrder(TreeNode root) { if(root == null) return new ArrayList<>(); List<List<Integer>> res = new ArrayList<>(); dfs(res,root,0); return res; } public void dfs(List<List<Integer>> res,TreeNode root,Integer level){ if(root == null) return; if(level >= res.size()){ res.add(new ArrayList()); } if((level & 1) == 0) res.get(level).add(root.val); else res.get(level).add(0,node.val); dfs(res,root.left,level+1); dfs(res,root.right,level+1); }