题目: 二叉树的锯齿形层次遍历 middle
给定一个二叉树,返回其节点值的锯齿形层次遍历。
(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
package leetCode.BFS;
import java.util.*;
public class lc_bfs_103_zigzagLevelOrder {
/*
题目: 二叉树的锯齿形层次遍历 middle
给定一个二叉树,返回其节点值的锯齿形层次遍历。
(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层次遍历如下:
[
[3],
[20,9],
[15,7]
]
*/
/*
思路:
1)官方方法:nodeQue的顺序不变,valQue处理顺序。使用一个双端队列LinkedList处理
2)我的方法:valQue的顺序不变,nodeQue处理顺序。使用两个栈ArrayDeque处理
*/
/**
* 我的方法:valQue的顺序不变,nodeQue处理顺序。leetCode执行效率不够好,但也是O(n)啊,很奇怪!
* 使用两个stack,分别存放奇数层(odd)和偶数层(even)的结点
* odd按左右的顺序,存放子节点到even;even按右左的顺序存放子节点到odd,交替执行。
* level按顺序存放结点值就行。
*
* @param root
* @return
*/
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> ans = new LinkedList<>();
if (root == null)
return ans;
Deque<TreeNode> oddNodeQue = new ArrayDeque<>();//存放奇数层结点
Deque<TreeNode> evenNodeQue = new ArrayDeque<>();//存放偶数层结点
oddNodeQue.push(root);
while (!oddNodeQue.isEmpty() || !evenNodeQue.isEmpty()) {//本次while循环可以同时遍历一次odd和even
List<Integer> valQueue = new LinkedList<>();
while (!oddNodeQue.isEmpty()) {
TreeNode node = oddNodeQue.pop();
valQueue.add(node.val);
if (node.left != null)//先左再右
evenNodeQue.push(node.left);
if (node.right != null)
evenNodeQue.push(node.right);
}
ans.add(new LinkedList<>(valQueue));
valQueue = new LinkedList<>();//在处理even前清空level队列
while (!evenNodeQue.isEmpty()) {
TreeNode node = evenNodeQue.pop();
valQueue.add(node.val);
if (node.right != null)//先右再左
oddNodeQue.push(node.right);
if (node.left != null)
oddNodeQue.push(node.left);
}
if (valQueue.size() != 0)//最后一层是奇数层时,如果不加判断会加入空level
ans.add(new LinkedList<>(valQueue));
}
return ans;
}
/**
* 官方的方法:nodeQue的顺序不变,valQue处理顺序。O(n),执行效率更好,不懂为啥
* 和经典的层序遍历差不多。
* 存放node时都按照左右顺序存放
* 关键是使用双端队列的addLast和addFirst方法
* 在添加值到valQue时,用left_order判断valQue是否需要逆序存放,该层遍历完left_order取反
*
* @param root
* @return
*/
public List<List<Integer>> zigzagLevelOrder2(TreeNode root) {
List<List<Integer>> ans = new LinkedList<>();
if (root == null)
return ans;
LinkedList<TreeNode> nodeQue = new LinkedList<>();
nodeQue.add(root);
boolean left_order = true;//用left_order判断valQue是否需要逆序存放
LinkedList<Integer> valQue = new LinkedList<>();
int count = 0;
while (!nodeQue.isEmpty()) {
count = nodeQue.size();//该层要遍历的结点数
while (count > 0) {
TreeNode cur = nodeQue.poll();
if (left_order)//判断是否要逆序存放到valQue
valQue.addLast(cur.val);
else
valQue.addFirst(cur.val);
if (cur.left != null)
nodeQue.add(cur.left);
if (cur.right != null)
nodeQue.add(cur.right);
count--;
}
ans.add(valQue);
valQue = new LinkedList<>();//清空
left_order = !left_order;//该层遍历完取反
}
return ans;
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
}