LeetCode 637:二叉树层次平均值计算与BFS/DFS实现
2026/9/14 11:44:34 网站建设 项目流程

1. 题目解析与核心思路

1.1 题目要求理解

LeetCode 637题要求我们计算二叉树每一层节点的平均值。给定一个二叉树的根节点root,需要返回一个数组,其中每个元素代表对应层所有节点值的平均值。

示例输入输出非常直观:

  • 输入:root = [3,9,20,null,null,15,7]
  • 输出:[3.00000,14.50000,11.00000]

这表示:

  • 第0层(根节点层)只有节点3,平均值就是3
  • 第1层有节点9和20,(9+20)/2=14.5
  • 第2层有节点15和7,(15+7)/2=11

1.2 解题关键点分析

解决这个问题的核心在于:

  1. 层次遍历:需要按层访问二叉树节点
  2. 层间分隔:需要明确知道哪些节点属于同一层
  3. 平均值计算:对每层节点值求和并计算平均值

层次遍历是二叉树算法中的基础操作,与先序、中序、后序遍历不同,它按照树的深度逐层访问节点。这种遍历方式非常适合解决与"层"相关的问题。

2. 算法设计与实现方案

2.1 广度优先搜索(BFS)方案

BFS是解决层次遍历问题的经典方法。我们可以使用队列来实现:

from collections import deque def averageOfLevels(root): if not root: return [] result = [] queue = deque([root]) while queue: level_size = len(queue) level_sum = 0 for _ in range(level_size): node = queue.popleft() level_sum += node.val if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_sum / level_size) return result

这个实现的关键点:

  1. 使用队列存储待访问节点
  2. 每次处理一层的所有节点(通过level_size控制)
  3. 在访问节点时将其子节点加入队列
  4. 计算当前层的平均值并加入结果列表

注意:Python中使用collections.deque而非list实现队列,因为deque的popleft()操作是O(1)时间复杂度,而list的pop(0)是O(n)。

2.2 深度优先搜索(DFS)方案

虽然BFS更直观,但DFS也可以解决这个问题,通过记录每个节点的深度:

def averageOfLevels(root): level_info = [] def dfs(node, depth): if not node: return if depth >= len(level_info): level_info.append([0, 0]) # [sum, count] level_info[depth][0] += node.val level_info[depth][1] += 1 dfs(node.left, depth + 1) dfs(node.right, depth + 1) dfs(root, 0) return [s / c for s, c in level_info]

DFS方案的特点:

  1. 使用递归实现,代码更简洁
  2. 需要维护一个level_info数组记录每层的总和和节点数
  3. 最后统一计算平均值

2.3 两种方案的比较

特性BFS方案DFS方案
时间复杂度O(n)O(n)
空间复杂度O(m) - m为最宽层的节点数O(h) - h为树的高度
适用场景更适合层次相关问题适合需要深度信息的场景
实现难度中等,需要处理队列简单,递归实现
扩展性容易扩展为其他层次操作需要修改递归参数

对于这个问题,BFS通常是首选,因为:

  1. 更直观反映层次遍历的过程
  2. 不需要递归,避免栈溢出风险
  3. 空间复杂度在最坏情况下可能更优(对于极度不平衡的树)

3. 算法优化与边界处理

3.1 大数处理与精度问题

当处理极大数时,简单的累加可能导致溢出。我们可以改进计算方式:

def averageOfLevels(root): if not root: return [] result = [] queue = deque([root]) while queue: level_size = len(queue) level_avg = 0 for i in range(level_size): node = queue.popleft() # 递推式计算平均值,避免大数相加 level_avg += (node.val - level_avg) / (i + 1) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_avg) return result

这种计算方式通过递推式更新平均值,可以避免大数相加导致的溢出问题。

3.2 空树和边界情况处理

健壮的算法需要考虑各种边界情况:

  1. 空树(root为None):应返回空列表
  2. 只有根节点的树:返回包含根节点值的列表
  3. 极度不平衡的树(如链表状的树):算法仍应正确工作

3.3 时间复杂度分析

两种算法的时间复杂度都是O(n),因为每个节点恰好被访问一次。空间复杂度:

  • BFS:取决于树的最大宽度,最坏O(n)
  • DFS:取决于树的高度,最坏O(n)(退化为链表的情况)

4. 代码实现细节与测试

4.1 Python完整实现

from collections import deque class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def averageOfLevels(root): if not root: return [] result = [] queue = deque([root]) while queue: level_size = len(queue) level_sum = 0 for _ in range(level_size): node = queue.popleft() level_sum += node.val if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_sum / level_size) return result # 测试用例 def test(): # 构建测试树:[3,9,20,null,null,15,7] root = TreeNode(3) root.left = TreeNode(9) root.right = TreeNode(20) root.right.left = TreeNode(15) root.right.right = TreeNode(7) print(averageOfLevels(root)) # 应输出 [3, 14.5, 11] test()

4.2 常见错误与调试

  1. 忘记处理空树:没有检查root是否为None直接开始遍历
  2. 层间分隔错误:在BFS中没有使用level_size来控制每层的处理
  3. 整数除法:在Python3中/是浮点除法,但某些语言中可能需要类型转换
  4. 队列实现错误:使用list代替deque导致性能问题

调试技巧:

  • 打印每层的节点值和计算过程
  • 对小规模测试用例手动验证
  • 使用LeetCode的可视化工具观察树结构

5. 算法扩展与应用

5.1 类似问题变种

掌握这个算法后,可以解决许多类似问题:

  1. 二叉树的最大深度
  2. 二叉树的最小深度
  3. 二叉树的右视图
  4. 二叉树的层序遍历
  5. 在每个树行中找最大值

5.2 实际应用场景

层次遍历在实际中有广泛应用:

  1. 社交网络中的好友推荐(按距离推荐)
  2. 组织结构图的层级分析
  3. 游戏中的AI决策树遍历
  4. 网络路由中的跳数计算

5.3 算法优化挑战

对于特别大的树,可以考虑:

  1. 并行化处理不同层次
  2. 使用更高效的数据结构
  3. 内存映射技术处理无法完全装入内存的树

我在实际刷题中发现,彻底理解层次遍历后,许多中等难度的树问题都能迎刃而解。建议初学者从这个问题入手,掌握BFS在树结构中的应用模式。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询