Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
return its zigzag level order traversal as:
[ [3], [20,9], [15,7] ]
解题思路:同样是对树进行广度优先遍历,由于遍历顺序有变化,所以不能用队列来存放遍历的节点,换用list,这样根据遍历的要求就可以从左到右或是从右到左进行对节点进行访问了。对于访问顺序,可以设置一个flag,根据flag的取值来执行不同的顺序,执行完一次,就将flag的值取反,这样就可以控制顺序了。
刚开始的时候,受102题的思路影响,在广度优先遍历孩子节点时,对孩子节点进行从左到右或者从右到左的存放,但是这样会导致一个问题:广度优先遍历得到的节点顺序被打乱了,下一次遍历的结果顺序是不可控制的,所以就改了一下思路,先将孩子节点进列表,然后根据flag的取值,对刚进列表的节点进行访问,将值存放,这样节点的值就是我们希望得到的顺序,而专门用来存放节点的列表的顺序就不会打乱了。
public class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
List<TreeNode> treelist = new ArrayList<TreeNode>(); //用list来当队列或栈
List<Integer> temp =new ArrayList<Integer>();
if(root!=null){
boolean flag=true; //为true时,从右向左访问treelist
treelist.add(root);
temp.add(root.val);
list.add(temp);
int min=0; //每次广度遍历某一层时,新进来的最左边的那个节点下标
int max=treelist.size(); //max是每次广度遍历某一层时,新进来的最右边的那个节点的下一个节点下标
//初始时,有根节点在temp中,进入循环,若条件不成立,说明某次没有新增的节点
while(temp.size()!=0){
temp = new ArrayList<Integer>();
//先对上一次进list的节点的孩子节点进行广度优先遍历
for(int i=min;i<max;i++){
TreeNode p = treelist.get(i);
if(p.left!=null){
treelist.add(p.left);
}
if(p.right!=null){
treelist.add(p.right);
}
}
//然后根据flag,对刚进列表的孩子节点的值进行存放
min=max; //每次遍历一层后,将两个下标一起后移,指向新进来的一段孩子节点的上下标
max = treelist.size();
if(flag){ //从右向左访问treelist
flag=false;
for(int i=max-1;i>=min;i--){ //从最后一个开始访问,访问
TreeNode p = treelist.get(i);
temp.add(p.val);
}
}
else{ //从左向右访问
flag=true;
for(int i=min;i<max;i++){
TreeNode p=treelist.get(i);
temp.add(p.val);
}
}
if(temp.size()!=0)
list.add(temp);
}
}
return list;
}
}