按之字型顺序打印二叉树
「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
读前福利,送大家一些电子书
问题描述
给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)。
要求:空间复杂度是O(n),时间复杂度是O(n)。
例如:给定的二叉树是 {1,2,3,#,#,4,5}
该二叉树之字形层序遍历的结果是[[1],[3,2],[4,5]]。
如题面解释,第一层是根节点,从左到右打印结果,第二层从右到左,第三层从左到右。
分析问题
根据题目要求,我们可以得出。
- 二叉树是从上到下按层进行输出的。
- 奇数层是按照从左到右打印,偶数层是按照从右到左打印
因为题目要求是按层进行遍历,所以我们可以知道是采用层序遍历的算法,不过这里和层序遍历有一点不同的是,对应偶数层,我们要逆序输出,即从右到左打印,所以我们需要引入一个双端队列数据结构,利用它两端都可以添加元素的特性,对奇数层和偶数层进行不同的处理。
- 奇数层:添加的队列的尾部
- 偶数层:添加到队列的头部
对于元素[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)。