算法思想一:层次遍历+栈

解题思路:

主要利用层次遍历二叉树的节点,并根据奇偶层添加二叉树的节点
算法流程:
1、特殊情况:如果树的根节点为空,则直接返回 【】
2、初始化:返回列表 res ,二叉树层索引 index,辅助栈
3、层次遍历循环 当栈为空跳出:
    1、新建列表tmp,用于临时存储当前层打印结果
    2、当前层打印循环:循环次数为当前层节点数量
        1、出栈:栈底元素,记为 node
        2、打印:将所在层节点值添加到 tmp中
        3、添加子节点:若 node 的左右子树不为空,则 入栈
    3、根据index判断所在层是奇数层还是偶数层:
        1、若为奇数层:将tmp直接添加到res中
        2、若为偶数层:将tmp倒序添加到res中
    4、index 加1
4、返回打印结果 res

图解:

代码展示:

Python版本
class Solution:
    def Print(self, pRoot):
        # write code here
        if not pRoot:
            return []
        res = []
        # 辅助栈
        stack = [pRoot]
        # 记录层数
        index = 1
        while stack:
            tmp = []
            for i in range(len(stack)): 
                node = stack[0]
                stack = stack[1:]
                tmp.append(node.val)
                if node.left:
                    stack.append(node.left)
                if node.right:
                    stack.append(node.right)
            # 判断所在树的层数,根据层数对 tmp 是否倒序存储
            if index % 2 == 0:
                res.append(tmp[::-1])
            else:
                res.append(tmp)
            index += 1 
        return res

复杂度分析:

时间复杂度O(N):N为二叉树的节点数量,层次遍历、进出栈
空间复杂度O(N): 最差情况下,即当树为满二叉树时,最多有 N/2 个树节点 同时 在 stack 中,使用 O(N) 大小的额外空间。

算法思想二:层次遍历+双端队列(奇偶层逻辑分离)

解题思路:

方法一代码简短、容易实现;但需要判断每个节点的所在层奇偶性,即冗余了 N 次判断。通过将奇偶层逻辑拆分,可以消除冗余的判断。
算法流程:
与方法一对比,仅层次遍历过程有差别,此方法使用的是双端队列存储二叉树的节点
BFS 循环: 循环打印奇 / 偶数层,当 deque 为空时跳出;
1、打印奇数层: 从左向右 打印,先左后右 加入下层节点;
2、若 deque 为空,说明向下无偶数层,则跳出;
3、打印偶数层: 从右向左 打印,先右后左 加入下层节点;

代码展示:

JAVA版本
public class Solution {
    public ArrayList Print(TreeNode pRoot) {
        Dequedeque = new LinkedList<>();
        ArrayList res = new ArrayList<>();
        if(pRoot != null) deque.add(pRoot);
        while(!deque.isEmpty()) {
            // 打印奇数层
            ArrayListtmp = new ArrayList<>();
            for(int i = deque.size(); i > 0; i--) {
                // 从左向右打印
                TreeNode node = deque.removeFirst();
                tmp.add(node.val);
                // 先左后右加入下层节点
                if(node.left != null) deque.addLast(node.left);
                if(node.right != null) deque.addLast(node.right);
            }
            res.add(tmp);
            if(deque.isEmpty()) break; // 若为空则提前跳出
            // 打印偶数层
            tmp = new ArrayList<>();
            for(int i = deque.size(); i > 0; i--) {
                // 从右向左打印
                TreeNode node = deque.removeLast();
                tmp.add(node.val);
                // 先右后左加入下层节点
                if(node.right != null) deque.addFirst(node.right);
                if(node.left != null) deque.addFirst(node.left);
            }
            res.add(tmp);
        }
        return res;
    }

}

复杂度分析:

时间复杂度O(N):N为二叉树的节点数量,即 BFS 需循环 N 次,占用 O(N) ;双端队列的队首和队尾的添加和删除操作的时间复杂度均为 O(1)
空间复杂度O(N): 最差情况下,即当树为满二叉树时,最多有 N/2 个树节点 同时 在 deque 中,使用 O(N) 大小的额外空间。