题目:二叉树的之字形层序遍历

描述:给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如:给定的二叉树是{3,9,20,#,#,15,7},

该二叉树之字形层序遍历的结果是[ [3], [20,9], [15,7] ]

示例1输入:{1,#,2},返回值:[[1],[2]]

解法一:

思路分析:因为是要将二叉树进行之字形层序遍历,所以我们采用双栈进行,排序规则为第一层通过正序输出,第二层逆序输出,第三层正序输出,通过依次类推,实现之字形排序,使用栈的性质(先进后出),先进入栈的数据最后再出栈,为了能够实现逆序遍历,将二叉树的第二层结点保存在栈1中,重新设置栈2存储下一层结点,使用stackout表示存储当前层结点的栈。stackIn表示存储下一层节点的栈,从左往右遍历(正向遍历)时,需要存储当前节点的左节点stackIn中;从右往左遍历(反向遍历)时,需要存储当前节点的右节点stackIn中

实例分析:以二叉树{3,9,20,#,#,15,7}为例,将根节点3存入stack1中,首先遍历的方向为从左往右遍历,其中stack1为stackout,stack2为stackin,当遍历完成后,stack1为空,stack2中存储着第二层的结点,遍历时需要不断pop出stackout中的结点,添加到arraylist中,从而可以得到第一层的顺序遍历。

树:

—>

3

将3存入stack1中

9

20

stack2

15

7


当遍历完第一层后,将方向反转,变为从右往左遍历,此时stack2为stackout,stack1为stackin,遍历完成后stack2为空,stack1中存储着第三层的结点,还是需要不断的pop出stackout中的结点,添加到arraylist中,得到第二层的逆序遍历。


树:

3

9

20

<—stack2

15

7

stack3


依次类推,返回最终值[ [3], [20,9], [15,7] ]。

Java代码为:


import java.util.*;
 
/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */
 
public class Solution {
    /**
     *
     * @param root TreeNode类
     * @return int整型ArrayList<arraylist><>>
     */
    public ArrayList zigzagLevelOrder (TreeNode root) {
        // write code here
        ArrayList cache = new ArrayList<>();
        if(root == null)
            return cache;
        Deque stack1 = new LinkedList<>();//设置双栈
        Deque stack2 = new LinkedList<>();
        stack1.push(root);//将根节点压入栈1
        boolean isfound = true;//设置方向
        
        while(stack1.isEmpty() == false || stack2.isEmpty() == false){//当前栈是否还有元素
            DequestackOut = stack1.isEmpty() ? stack2 : stack1;
            DequestackIn = stack1.isEmpty() ? stack1 : stack2;
            //stackout存储当前层,stackin存储下一层
            cache.add(new ArrayList<>());
            //遍历当前层的结点
            while(stackOut.isEmpty() == false){
                //栈顶出栈
                TreeNode cur = stackOut.pop();
                //添加到Arraylist里边
                cache.get(cache.size() - 1).add(cur.val);
                if (isfound) {
                    //如果方向是从左往右,则先遍历当前节点的左节点
                    pushNode(stackIn, cur.left);
                    pushNode(stackIn, cur.right);
                }
                else {
                    //如果方向是从右往左,则先遍历当前节点的右节点
                    pushNode(stackIn, cur.right);
                    pushNode(stackIn, cur.left);
                }
            }
            isfound = !isfound;//改变方向
        }
        return cache;
    }
    
    private void pushNode(Dequestack, TreeNode node) {//将结点存入栈中
        if (node != null) {
            stack.push(node);
        }
    }
}</arraylist>


遍历树中的每一个元素,时间复杂度为O(N),空间复杂度为O(N)。


解法二:

思路分析:首先创建队列,将结点加入到队列当中,利用先进先出原则,依次弹出栈。将每次弹出结点的值保存到链表当中,如果是奇数层的话,就采用尾插,如果为偶数层的话,执行头插,如果弹出的结点中有左右子树,则将左右子结点加入到当前队列当中,在每一层遍历完成后都要将这一层的结点加入到链表当中。

树:

3(头插)

9

20

(尾插)

15

7

(头插)

返回最终值[ [3], [20,9], [15,7] ]

具体Java代码为:


import java.util.*;
 
/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */
public class Solution {
    /**
     *
     * @param root TreeNode类
     * @return int整型ArrayList<arraylist><>>
     */
    public ArrayList zigzagLevelOrder (TreeNode root) {
        ArrayList res = new ArrayList<>();
        Queueque = new LinkedList<>();//创建队列
        if(root != null){
            que.add(root);
        }
        while(!que.isEmpty()){
            ArrayListtmp = new ArrayList<>();//存储每一层节点
            for(int i = que.size();i > 0;i--){//遍历当前层的节点
                TreeNode node = que.poll();//弹出队列中的节点
                if((res.size() + 1) % 2 != 0){
                    tmp.add(node.val);//奇数尾插
                }
                else{
                    tmp.add(0,node.val);//偶数层头插
                }
                if(node.left!=null){//如果左子节点不为空,则将其加入到队列中
                    que.add(node.left);
                }
                if(node.right!=null){//如果右子节点不为空,则将其加入到队列中
                    que.add(node.right);
                }
            }
            res.add(tmp);//将这一层的节点加入到res中
        }
        return res;
    }
}</arraylist>


其时间复杂度为O(N),设置链表对象和队列用与存储数字,所以其空间复杂度为O(N)。