103. 二叉树的锯齿形层序遍历

难度中等525

给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如: 给定二叉树 [3,9,20,null,null,15,7],

1
2
3
4
5
   3
  / \
 9  20
   /  \
  15   7

返回锯齿形层序遍历如下:

1
2
3
4
5
[
 [3],
 [20,9],
 [15,7]
]

通过次数173,983

提交次数304,411

这一题的坑还是非常多的,没有那么容易。最初想法是改一改层序遍历的代码就行了,想用一个队列完成,根据flag决定出队列的顺序。发现不行,因为队列是一遍增加一遍移出的。入上图当队列是[9 20],从尾部移出得到20,9.看起来没错,但是在移出9时,又像队列的尾部增加了15和7,队列变成了[9 15 7]再移出尾部就错了。

这是想通过双队列的方式,增加到新的队列中,在移出9时,[15 7]在下一个队列。看起来比较完美,一试又不对。试想移出9时插入[15 7] 再移出20时,插入了20的子节点(这里假设它有2个子节点 1 2),会发现倒序的里面,是左节点,右节点的顺序,很奇怪。此时又想过根据flag实现从右到左,但是这似乎让顺序直接变成倒叙的队列,下一行就不必改变出队列的顺序,一直倒序出就可以了。

但是这种太麻烦,我最后还是用了顺序的bfs,但是根据flag的值,让输出的值取反,实现不对bfs的过程做出任何改变,较为简易。

 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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        ArrayList<List<Integer>> ans=new ArrayList<>();
        
        if(root==null) return ans;
        LinkedList<TreeNode> queue=new LinkedList<>();
        LinkedList<TreeNode> queueNext=new LinkedList<>();
         LinkedList<TreeNode> queueCopy=new LinkedList<>();
        ArrayList<Integer> zigzag=new ArrayList<>();
       
        queue.add(root);
        queueCopy.add(root);
        int flag=1;
        int cur=1;
        int next=0;
      
        
        zigzag=new ArrayList<>();
        while(!queue.isEmpty()&&!queueCopy.isEmpty()){
            TreeNode t=null;
            TreeNode tcopy=null;
            if(flag==1){t=queue.removeFirst();}
            else if(flag==-1){t=queue.removeLast();}
            tcopy=queueCopy.poll();
            zigzag.add(t.val);
            


            cur--;
            
            if(tcopy.left!=null){
                queueNext.add(tcopy.left);
                next++;
            }
            if(tcopy.right!=null){
                queueNext.add(tcopy.right);
                next++;
            }
            
                
            
            if(cur==0){
                ans.add(zigzag);
              //  System.out.println(queueNext);
               zigzag=new ArrayList<>();
               flag=-flag;
               queue=new LinkedList(queueNext);
               queueCopy=new LinkedList(queueNext);
              // 注意不能传地址:queue=queueNext 这样会使queue 和queueNext指向的是同一个地址
               queueNext.clear();


                cur=next;
                next=0;

            }
        }
      
        return ans;


    }
}