高频算法面试题(十九)- 按之字形顺序打印二叉树

416 阅读3分钟

「这是我参与11月更文挑战的第 10 天,活动详情查看:2021最后一次更文挑战

刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能

按之字形顺序打印二叉树

题目来源LeetCode - 剑指 Offer 32 - III. 从上到下打印二叉树 III

题目描述

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推

例如:

给定二叉树:

[3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [20,9],
  [15,7]
]

示例

示例 1

输入:{1,2,3,#,#,4,5}
返回值:[[1],[3,2],[4,5]]
说明:如题面解释,第一层是根节点,从左到右打印结果,第二层从右到左,第三层从左到右。

示例 2

输入:{8,6,10,5,7,9,11}
返回值:[[8],[10,6],[5,7,9,11]]

示例 3

输入:{1,2,3,4,5}
返回值:[[1],[3,2],[4,5]]

解题

解法一:双端队列

思路

我最开始想这个题的时候,其实是用的栈+队列,奇数层入栈、偶数层入队列,然后取结点的时候,先取右节点,再取左节点,发现这样做,到第4层的时候就不对了

然后就想到双端队列,因为有了前边那种思路,很容易想到用双端队列,用双端队列,这道题就简单了

首先需要借助两个队列

  • queue:如果queue中的结点是偶数层的,首先将队列中的元素,顺序放入到结果集res中,然后逆序访问queue中的元素,将每个元素的子节点,按照先右节点后左节点的顺序,将子节点放入到临时队列tmpQueue中。如果是奇数层,首先将队列中的元素,顺序放入到结果集res中,然后逆序访问queue中的元素,将每个元素的子节点,按照先左节点后右节点的顺序,将子节点放入到临时队列tmpQueue中
  • tmpQueue:用于临时存储每一层的结点

文字比较抽象,看图

2.png level = 0(偶数层)

  1. 先顺序遍历queue中的元素,将其放入结果集res
  2. 逆序取出queue中的元素,按照先右子树后左子树的顺序,将下一层的节点放入tmpQueue中
  3. 将tmpQueue赋值给queue

3.png level = 1(奇数层)

  1. 先顺序遍历queue中的元素,将其放入结果集res
  2. 逆序取出queue中的元素,按照先左子树后右子树的顺序,将下一层的节点放入tmpQueue中
  3. 将tmpQueue赋值给queue

image.png

level = 2(偶数层)

  1. 先顺序遍历queue中的元素,将其放入结果集res
  2. 逆序取出queue中的元素,按照先右子树后左子树的顺序,将下一层的节点放入tmpQueue中
  3. 将tmpQueue赋值给queue

image.png

level = 3(奇数层)

image.png

代码

var res [][]int
	if root == nil {
		return res
	}
	queue := []*TreeNode{root}
	
	level := 0
	for len(queue) != 0 {

		tmpQueue := []*TreeNode{}
		res = append(res, []int{})

		for _, node := range queue {
			res[level] = append(res[level], node.Val)
		}
		if level % 2 == 0 {
			for i:=len(queue)-1; i >= 0; i-- {
				if queue[i].Right != nil {
					tmpQueue = append(tmpQueue, queue[i].Right)
				}
				if queue[i].Left != nil {
					tmpQueue = append(tmpQueue, queue[i].Left)
				}
			}
		} else {
			for i:=len(queue)-1; i >= 0; i-- {
				if queue[i].Left != nil {
					tmpQueue = append(tmpQueue, queue[i].Left)
				}
				if queue[i].Right != nil {
					tmpQueue = append(tmpQueue, queue[i].Right)
				}
			}
		}

		queue = tmpQueue
		level++

	}

	return res