二叉树的层序遍历python

题目链接 102. 二叉树的层序遍历 - 力扣(Leetcode)

记录两种写法,一种是作者看错题目要求后,在错误代码上硬着头皮改出来的代码,(记录在博客中随时鞭打自己)。一种是根据优秀题解理解后重新编写的代码

这道题我看了许多题解,没有找到时间与空间都优秀的解法,基本都是时间与空间要牺牲一个

一. 作者的一坨**代码(很多冗余的条件判断)

 如果读者想见识作者当时的愚蠢想法,可以当乐子看一看,虽然也能100%通过,但是实在差。

严重缺点:flag的判断太过于鸡肋,万一题目没给你结点值范围直接原地爆炸

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root: return []
        # 根节点为空返回[]
        res = [0]  # 0 完全作占位置作用,作者为了后面得索引好对齐才放的。输出时不带上
        yes, no = 1, 0  # 标志是否写入res了,因为它可能有子结点且遍历顺序较后,需要将其暂存于栈
        stack = [(1, no, root)]
        # (深度,是否进res了,结点)

        while stack:

            dep, flag, node = stack.pop()
            dep_now = dep + 1 # 子结点的深度
            right_val, left_val = 10000, 10000  # 题目给出的结点值范围
            # 原本想用False 但是万一结点值为0 ,后续判断会产生错误
            son_through = []  # 父结点的子结点的遍历
            if not flag: res.append([node.val]) # 这个flag完全只作用于root,作者当时脑子瓦特写的太复杂
            # 因为明明检查到有结点当时就写入了
            if node.right:
                right_val = node.right.val
                stack.append((dep_now, yes, node.right))
            if node.left:
                left_val = node.left.val
                stack.append((dep_now, yes, node.left))
            # 进栈顺序应为右结点先
            # 但是进res顺序应该为左结点先
            if -1000 <= left_val <= 1000: son_through.append(left_val)
            if -1000 <= right_val <= 1000: son_through.append(right_val)
            if len(res) > dep_now:
                res[dep_now].extend(son_through)
            # 作者当时只合并了同父结点的结点值,并没有合并同层次结点
            # 深度的作用就在这里,res中每一个[]中的值都是同深度的也就是同层次的
            # 按照上面的循环处理方式,左结点C的子结点可能比 同层次结点(与C)更早进入res,但是不用担心,不同层次在res中不在一个子列表中
            # 比如深度为3(深度为2时右结点的子结点)的右子树结点,在res中应该加入的位置就是res[3](前面res[0]是0,所以索引对齐了)
            # 当遍历到右子树的深度为2的结点时判断res长度长于本身深度,就代表着深度>2的结点已经进res了
            # 那么合并后的同父结点值就不能直接插入到res的尾端而是应该合并到前面同深度的子列表中去
            elif son_through:
                res.append(son_through)
            # 该深度第一次出现,直接插入到res尾端
        return res[1:]
        # 不带上开头的0

 

 

 

 二 代码改进

找遍了题解,没有找到这个层序遍历的运行结果时间与空间兼得的。要么时间短了空间占用多,要么空间占用少了时间长了,总有一个是红色的。

下面这个方法代码的复杂程度较低,简单易懂

from collections import deque
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root: return []
        res = []
        queue = deque([root])
        # 队列,创建时加入root
        
        while queue:
            level_through = [] 
            # 用来存放这个层次的遍历结果
            for _ in range(len(queue)):
                # 提一句:本次循环结束前就算len(queue)变化,用的也是一开始的值。
                # 所以不用担心过程中入队列会影响结果。
                # 每次for循环的对象都是一个层次(深度)上的所有结点,
                # 这些结点的子结点(就是下一深度的结点)按照从左到右入队列
                node = queue.popleft()
                level_through.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(level_through)
        return res

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值