The problem
You get the root of a non-empty binary tree. Return a list where the i-th number is the average of all node values on level i (the root is level 0). Answers within 10⁻⁵ of the true value are accepted.
Input: 3
/ \
9 20
/ \
15 7
Output: [3.0, 14.5, 11.0]Level 0 is 3; level 1 is (9 + 20) / 2 = 14.5; level 2 is (15 + 7) / 2 = 11.0.
How to think about it
Start with brute force. Do any traversal (say DFS) and pass the depth along, adding each value into sums[depth] and counts[depth]. Then divide. That is actually O(n) and perfectly fine, but it needs two side arrays and it’s easy to get the indexing wrong.
The key insight: the question is about levels, and BFS visits a tree level by level. A queue that starts with the root and appends children as it pops nodes processes all of level 0, then all of level 1, and so on. The only extra trick is knowing where one level ends: at the start of each round, len(q) is exactly the number of nodes on the current level. Pop that many, sum them, divide by that count.
Which pattern is this? Tree BFS, level-order traversal. The tell is any phrase like “each level”, “per depth” or “row by row” on a tree.
Approach
- Put the root in a queue.
- While the queue is not empty:
- take
n = len(q), the size of the current level, and sets = 0, - pop
nnodes, adding each value tosand pushing its children, - append
s / nto the result.
- take
- Return the result.
Solution
from collections import deque
def average_of_levels(root):
res = []; q = deque([root])
while q:
n = len(q); s = 0 # n = number of nodes on this level
for _ in range(n):
node = q.popleft(); s += node.val
if node.left: q.append(node.left) # children belong to the next level
if node.right: q.append(node.right)
res.append(s / n)
return res
# average_of_levels([3,9,20,null,null,15,7]) -> [3.0, 14.5, 11.0]Dry run
On the example tree:
| Level | Nodes popped | n |
s |
Average | Queue after the level |
|---|---|---|---|---|---|
| 0 | 3 | 1 | 3 | 3.0 | 9, 20 |
| 1 | 9, 20 | 2 | 29 | 14.5 | 15, 7 |
| 2 | 15, 7 | 2 | 22 | 11.0 | empty |
Result: [3.0, 14.5, 11.0].
Complexity
- Time: O(n). Every node is enqueued and dequeued exactly once.
- Space: O(w), where
wis the widest level. The queue only ever holds about one level plus some of the next. For a complete tree that is about n/2 nodes, so O(n) in the worst case.
Edge cases and pitfalls
- Empty tree: the problem guarantees at least one node. If it didn’t, this code would try to read
None.val; addif not root: return []. - Single node: returns
[root.val]as a float. - Measuring the level inside the loop.
len(q)changes as you push children. Snapshot it intonbefore thefor. - Integer division. In Python 3
/is true division. In Java/C++, cast to double and watch for int overflow on large sums. - Using a list as a queue.
list.pop(0)is O(n). Usecollections.deque.
Related problems
- Binary Tree Level Order Traversal (LeetCode 102): the same loop, collecting the values instead of averaging them.
- Binary Tree Right Side View (LeetCode 199): the same loop, keeping only the last value of each level.
- Minimum Depth of Binary Tree (LeetCode 111): BFS that stops at the first leaf.
- 1.Average of Levels in Binary Tree (LeetCode 637)
- 2.Minimum Depth of Binary Tree (LeetCode 111)
- 3.Cousins in Binary Tree (LeetCode 993)
- 4.Binary Tree Level Order Traversal (LeetCode 102)
- 5.Binary Tree Level Order Traversal II (LeetCode 107)
- 6.Binary Tree Right Side View (LeetCode 199)
- 7.Binary Tree Zigzag Level Order Traversal (LeetCode 103)
- 8.Populating Next Right Pointers in Each Node (LeetCode 116)
- 9.Rotting Oranges (LeetCode 994)
- 10.Word Ladder (LeetCode 127)