二叉树层序遍历的6种变体:从基础到秒杀面试

层序遍历(Level Order Traversal) 是二叉树最高频的算法考点之一,更是微软、字节等大厂面试的“必考题”。除了基础版本,面试官往往会要求写出至少2~3种变体。本文将以 6种层序遍历变体 为核心,手把手教你写出面试官无法挑剔的代码,并提供可直接复用的代码模板!


一、基础回顾:标准层序遍历

1.1 核心思想

使用 队列(Queue) 实现广度优先搜索(BFS),按层级输出节点值:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def level_order(root):
    if not root:
        return []
    queue = [root]
    result = []
    while queue:
        level = []
        for _ in range(len(queue)):  # 固定当前层的节点数量
            node = queue.pop(0)
            level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        result.append(level)
    return result

1.2 复杂度分析

  • 时间复杂度:O(n),每个节点进出队列一次
  • 空间复杂度:O(n),队列最大存储宽度节点数

二、变体1:之字形遍历(锯齿形层序)

2.1 题目场景

  • LeetCode 103:二叉树的锯齿形层序遍历
  • 要求:奇数层从左到右,偶数层从右到左输出

2.2 实现方案

通过 层级奇偶标记 控制反转方向:

def zigzag_level_order(root):
    if not root:
        return []
    queue = [root]
    result = []
    reverse = False  # 反转标记
    while queue:
        level = []
        for _ in range(len(queue)):
            node = queue.pop(0)
            level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        result.append(level[::-1] if reverse else level)
        reverse = not reverse  # 切换反转状态
    return result

三、变体2:自底向上层序遍历

3.1 应用场景

  • LeetCode 107:二叉树的层序遍历 II
  • 要求:从叶子节点所在层开始,逐层向上遍历

3.2 实现技巧

在基础层序遍历后,直接 反转结果列表

def level_order_bottom(root):
    result = level_order(root)  # 复用基础层序遍历
    return result[::-1]

四、变体3:带层级分隔符的输出

4.1 面试需求

要求每层节点用特定符号分隔(如 #),便于可视化展示:

输入:
    1
   / \
  2   3
输出:["1", "2#3"]

4.2 代码实现

def level_separator(root):
    if not root:
        return []
    queue = [root]
    result = []
    while queue:
        level = []
        level_str = []
        for _ in range(len(queue)):
            node = queue.pop(0)
            level_str.append(str(node.val))
            if node.left:
                queue.append(node.left)
                level.append(node.left)
            if node.right:
                queue.append(node.right)
                level.append(node.right)
        result.append("#".join(level_str))
    return result

五、变体4:统计每层节点数

5.1 进阶问题

  • 问题示例:求二叉树的最大宽度(LeetCode 662)
  • 技巧:记录每层第一个和最后一个节点的位置索引

5.2 带位置索引的层序遍历

def width_of_binary_tree(root):
    if not root:
        return 0
    queue = [(root, 0)]  # (节点, 位置索引)
    max_width = 1
    while queue:
        level_size = len(queue)
        first_pos = queue[0][1]
        last_pos = queue[-1][1]
        max_width = max(max_width, last_pos - first_pos + 1)
        for _ in range(level_size):
            node, pos = queue.pop(0)
            if node.left:
                queue.append((node.left, 2 * pos))
            if node.right:
                queue.append((node.right, 2 * pos + 1))
    return max_width

六、变体5:右视图(输出每层最后一个节点)

6.1 高频考题

  • LeetCode 199:二叉树的右视图
  • 要求:从右侧视角能看到的节点值集合

6.2 实现方案

每层遍历时,仅记录最后一个节点:

def right_side_view(root):
    if not root:
        return []
    queue = [root]
    result = []
    while queue:
        level_size = len(queue)
        for i in range(level_size):
            node = queue.pop(0)
            if i == level_size - 1:  # 每层最后一个节点
                result.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
    return result

七、变体6:N叉树的层序遍历

7.1 扩展场景

当树结构从二叉树变为N叉树时,需遍历所有子节点:

class NTreeNode:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children or []

def nary_level_order(root):
    if not root:
        return []
    queue = [root]
    result = []
    while queue:
        level = []
        for _ in range(len(queue)):
            node = queue.pop(0)
            level.append(node.val)
            for child in node.children:  # 遍历所有子节点
                queue.append(child)
        result.append(level)
    return result

八、面试技巧与高频追问

8.1 代码注意事项

  1. 空节点处理:始终检查 node.left/node.right 是否存在
  2. 队列实现选择:Python中用 deque 更高效(本文用列表简化理解)
  3. 层级固定技巧for _ in range(len(queue)) 是关键

8.2 高频追问与回答

  • Q1:如何用DFS实现层序遍历?
    A1:递归时记录当前深度,按层级存储节点(空间复杂度O(h),h为树高)

  • Q2:如何统计每层的平均值/最大值?
    A2:遍历每层时计算累加值或比较最大值

  • Q3:如果要求输出每层的第一个节点(左视图)?
    A3:记录每层的第一个节点(与右视图对称)


九、性能对比与总结

变体类型时间复杂度空间复杂度适用场景
基础层序遍历O(n)O(w)常规层级输出
之字形遍历O(n)O(w)交替方向输出
右视图/左视图O(n)O(w)边缘节点可视化
最大宽度统计O(n)O(w)树的结构分析
N叉树层序遍历O(n)O(w)多子节点树结构

相关LeetCode练习题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值