按之字型顺序打印二叉树

289 阅读2分钟

按之字型顺序打印二叉树

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

读前福利送大家一些电子书

问题描述

给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)。

要求:空间复杂度是O(n),时间复杂度是O(n)。

例如:给定的二叉树是 {1,2,3,#,#,4,5}

image-20211002110812938

该二叉树之字形层序遍历的结果是[[1],[3,2],[4,5]]。

如题面解释,第一层是根节点,从左到右打印结果,第二层从右到左,第三层从左到右。

分析问题

根据题目要求,我们可以得出。

  1. 二叉树是从上到下按层进行输出的。
  2. 奇数层是按照从左到右打印,偶数层是按照从右到左打印

image-20211002112625418

因为题目要求是按层进行遍历,所以我们可以知道是采用层序遍历的算法,不过这里和层序遍历有一点不同的是,对应偶数层,我们要逆序输出,即从右到左打印,所以我们需要引入一个双端队列数据结构,利用它两端都可以添加元素的特性,对奇数层和偶数层进行不同的处理。

  • 奇数层:添加的队列的尾部
  • 偶数层:添加到队列的头部

对于元素[1,2,3],如果从尾部添加,则遍历完成时,队列中元素的顺序是[1, 2, 3] ,输出后是正序的。如果从头部添加,则遍历完成时,队列中元素的顺序是[3, 2, 1],输出后是逆序的,从而解决问题。最后,我们来看一下代码的实现。

import collections
def levelOrder(root):
    #如果根节点为空,直接返回空值
    if not root:
        return []
    res = []
    deque = collections.deque([root])
    #队列不为空时
    while deque:
        #双端队列,保存遍历的元素
        tmp = collections.deque()
        #遍历该层元素
        for _ in range(len(deque)):
            node = deque.popleft()
            #偶数层,从前边插入,即队头
            if len(res) % 2:
                tmp.appendleft(node.val)
            else:
                #奇数层,从后边插入,即队尾
                tmp.append(node.val)
            #node的左右孩子入队
            if node.left: 
                deque.append(node.left)
            if node.right: 
                deque.append(node.right)
        #添加到结果列表中        
        res.append(list(tmp))
    return res

该算法的时间复杂度和空间复杂度都是O(N)。

其实我们也可以不使用双端队列,我们可以直接使用列表来实现。如果是奇数层,我们直接添加到结果中,如果是偶数层,我们把列表逆置,然后再加入结果。

def levelOrder(root):
    if not root:
        return []
    res = []
    queue = collections.deque()
    queue.append(root)
    while queue:
        tmp = []
        for _ in range(len(queue)):
            node = queue.popleft()
            tmp.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        if len(res) % 2==0:
            #偶数层,逆序添加
            res.append(tmp[::-1])
        else:
            #奇数层
            res.append(tmp)
    return res

该算法的时间复杂度和空间复杂度都是O(N)。