这是一道二叉树的Z字形遍历的问题。原本觉得不是很难,但中间磕磕绊绊遇到了许多小问题,费了我很大功夫才通过。首先和一般的BFS不同,Z字形遍历需要在一层遍历之后在下一层反向遍历。由于BFS常常用到队列这个数据结构,根据这个特点,我自然而然地想到了用栈来实现这种遍历。因为一层的遍历顺序正好和下一层是反的,先遍历到的结点在下一层是后遍历的。所以利用栈的“后进先出”的性质可以很方便地解决这个问题。由于奇偶层的遍历顺序相反,所以在入栈时需要考虑层数改变入栈的顺序,而出栈时不用考虑。一个值得注意的问题是Java在将一个对象加入另一个对象时,对原对象进行的改动会影响到被加入的对象。所以开始我对结果添加每一层的List并在添加后清空时,发现最后结果全是空的。当时百思不得其解,在调试之后才发现问题。所以在每次迭代之后手动new一个新的List就好啦。
代码如下:
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>>result=new ArrayList<List<Integer>> ();
if (root==null) return result;
List<Integer>row1=new ArrayList<Integer>();
Stack<TreeNode>node1=new Stack<TreeNode>();
row1.add(root.val);
node1.push(root);
result.add(row1);
//记录遍历到的下一层的结点数与当前的层数
int count=1;
int jiou=1;
while (true)
{
List<Integer>row=new ArrayList<Integer>();
//node是存储遍历到的下一层的结点的栈
Stack<TreeNode>node=new Stack<TreeNode>();
int t=0;
jiou++;
for (int i=0;i<count;i++)
{
TreeNode now=node1.pop();
if (jiou%2==1) t= t+Visitleft(row,node,now);
else t= t+Visitright(row,node,now);
}
count=t;
if (count==0)break;
//将树的这一行的结点在入栈后复制到原来的栈中,准备在遍历下一行后使用
node1=(Stack<TreeNode>)node.clone();
result.add(row);
}
return result;
}
public static int Visitleft (List<Integer>row,Stack<TreeNode>node,TreeNode le)
{
int num=0;
if (le.left!=null)
{
node.push(le.left);
row.add(le.left.val);
num++;
}
if (le.right!=null)
{
node.push(le.right);
row.add(le.right.val);
num++;
}
return num;
}
public static int Visitright (List<Integer>row, Stack<TreeNode>node,TreeNode ri)
{
int num=0;
if (ri.right!=null)
{
node.push(ri.right);
row.add(ri.right.val);
num++;
}
if (ri.left!=null)
{
node.push(ri.left);
row.add(ri.left.val);
num++;
}
return num;
}
}