【剑指offer】JZ78 把二叉树打印成多行

1 问题

给定一个节点数为 n 二叉树,要求从上到下按层打印二叉树的 val 值,同一层结点从左至右输出,每一层输出一行,将输出的结果存放到一个二维数组中返回。
例如:
给定的二叉树是{1,2,3,#,#,4,5}
在这里插入图片描述
该二叉树多行打印层序遍历的结果是
[
[1],
[2,3],
[4,5]
]

数据范围:二叉树的节点数 0≤n≤1000,0≤val≤1000
要求:空间复杂度 O(n),时间复杂度 O(n)

输入描述:给定一个二叉树的根节点

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

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

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

示例4
输入:{}
返回值:[]

2 答案

自己写的,队列

class Solution:
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        if not pRoot:
            return []
        ls = []
        ls.append(pRoot)
        res = []
        while ls:
            level = []
            for _ in range(len(ls)):
                cur = ls.pop(0)
                level.append(cur.val)
                if cur.left:   # 如果后面还会用到这个节点对象,就不要用.val
                    ls.append(cur.left)
                if cur.right:
                    ls.append(cur.right)
            if level:
                res.append(level)
        return res

在这里插入图片描述
官方解

  1. 非递归层次遍历,相同

题目要求将二叉树按行打印,即按层打印,其中每层分开。不难想到,要使用层次遍历,但是难点在于如何每层分开存储,从哪里知晓分开的时机?在层次遍历的时候,我们通常会借助队列(queue),事实上,队列中的值大有玄机,让我们一起来看看:

  • 当根节点进入队列时,队列长度为1,第一层节点数也为1
  • 若是根节点有两个子节点,push进队列后,队列长度为2,第二层节点数也为2;若是根节点一个子节点,push进队列后,队列长度为为1,第二层节点数也为1.
  • 由此,我们可知,每层的节点数等于进入该层时队列长度,因为刚进入该层时,这一层每个节点都会push进队列,而上一层的节点都出去了。

综上,反过来,每次只要在队列长度内循环,必定是一层,一层访问完毕再更新队列长度即可。

具体做法:

  • step 1:如果树为空,则返回空数组,没有任何打印结果。
  • step 2:使用队列辅助层次遍历,优先加入二叉树的根节点。
  • step 3:从根节点开始,每次进入一层的时候,记录队列的长度即本层的节点数,然后访问相应节点数全在同一个数组中,子节点加入队列中继续排队。
  • step 4:每次访问完一层将数组加入二维数组中再进入下一层。
class Solution:
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        res = []
        if pRoot is None:
            #如果是空,则直接返回空数组
            return res
        #队列存储,进行层次遍历
        q = [pRoot]
        while q:
            #记录二叉树的某一行
            row = []  
            n = len(q)
            #因先进入的是根节点,故每层节点多少,队列大小就是多少
            for i in range(n):
                #取出队首
                node = q.pop(0)
                row.append(node.val)
                #若是左右孩子存在,则存入左右孩子作为下一个层次
                if node.left:
                    #加入队尾
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
            res.append(row)
        return res
  1. 递归层次遍历

除了用队列非递归可以实现二叉树的层次遍历,我们也可以使用递归。但是递归前序遍历访问二叉树不是按照层次的顺序,但是因为“根左右”的次序,我们能保证每一层一定左边的元素先访问,后面再访问到同一层右边的元素。

要找到这个节点是第几层的,只是需要在函数中加入记录深度的变量,每往下一层深度加1,同时保存结果的数组正好对应每层一个数组,因此数字的大小正好是遍历的深度,由此可以实现递归。

  • step 1:记录输出的二维数组初始化为空,每到一层里面填出一个一维数组。
  • step 2:从根节点开始,深度为1开始进行递归,当前节点有值递归内容才继续进行,否则返回。
  • step 3:如果记录输出的二维数组长度小于当前层数,说明要新到了一层,我们新开辟一个一维数组加到最后。
  • step 4:因为“根左右”的顺序,同一层左边必定先访问,只需要根据层数在二维数组中找到相应的行号,添加在该行末尾就一定是层次遍历的次序。
class Solution:
    def traverse(self, root: TreeNode, res: List[List[int]], depth: int):
        if root:
            if len(res) < depth:
                res.append([])
            res[depth - 1].append(root.val)
            self.traverse(root.left, res, depth + 1)
            self.traverse(root.right, res, depth + 1)
    #层次遍历
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        res = []
        #树的层级从1开始递归计数
        #这样调用,res也是有改变的
        self.traverse(pRoot, res, 1) 
        return res

https://www.nowcoder.com/share/jump/9318638301700994523042

  • 17
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值