AlgoMaster Logo

Average of Levels in Binary Tree

Last Updated: April 3, 2026

easy

Understanding the Problem

We have a binary tree and we need to compute the average of all node values at each depth level. Level 0 is the root, level 1 is the root's children, level 2 is the grandchildren, and so on.

The word "each level" is the key here. We are not computing a single average over the whole tree. We need to group nodes by their depth, compute a separate average for each group, and return those averages in order from top to bottom.

This naturally leads us to think about level-order traversal. If we can process all nodes at the same depth together, computing averages becomes straightforward: sum the values, divide by the count. The question is just how we group them, and there are two clean ways to do it.

Key Constraints:

  • 1 <= number of nodes <= 10^4 -> With up to 10,000 nodes, O(n) and O(n log n) approaches are both fine. Even O(n^2) would work within limits, but there is no reason to go there.
  • -2^31 <= Node.val <= 2^31 - 1 -> Node values can be as large as Integer.MAX_VALUE or as small as Integer.MIN_VALUE. If we sum multiple such values, we can overflow a 32-bit integer. We need to use long (or equivalent) for the running sum at each level.

Approach 1: BFS (Level-Order Traversal)

Intuition

The most natural way to compute averages per level is to process the tree level by level. BFS does exactly this. We use a queue, and at each step, we know how many nodes are in the current level (it is the current size of the queue). We dequeue all of them, sum their values, count them, and compute the average. Then we enqueue their children, which form the next level.

The trick that makes BFS work level-by-level is capturing the queue size at the start of each level. Before we start dequeuing, we check how many nodes are in the queue right now. That number tells us exactly how many nodes belong to the current level. We process exactly that many, and anything we enqueue during processing belongs to the next level.

Algorithm

  1. If the root is null, return an empty list.
  2. Initialize a queue and add the root to it.
  3. While the queue is not empty:
    • Record the current size of the queue. This is the number of nodes at this level.
    • Initialize a running sum (using a long to avoid overflow).
    • Dequeue exactly that many nodes, adding each node's value to the sum and enqueuing its non-null children.
    • Compute the average as sum divided by count, and add it to the result list.
  4. Return the result list.

Example Walkthrough

1Start BFS: enqueue root (3)
3queue920157
1/6
1Enqueue root node 3
Front
3
Rear
1/6
1Result array starts empty
1/6

Code

BFS is already optimal in terms of time, but the queue can hold up to half the tree in memory for wide trees. What if we tracked level information during a DFS instead, using only O(h) stack space?

Approach 2: DFS (Depth-First Search)

Intuition

DFS does not process nodes level by level, but it does know the depth of every node it visits. If we pass the current depth along during recursion, we can accumulate the sum and count for each level in two parallel arrays. After the DFS finishes, we just divide each level's sum by its count to get the average.

Think of it this way: BFS groups nodes by level explicitly through the queue. DFS groups them implicitly by tagging each node with its depth and using that depth as an index into our tracking arrays. The end result is the same, but the traversal order is different.

This approach shines when the tree is very tall and narrow (like a skewed tree), because the call stack depth is O(h) and h could be much smaller than the queue width in BFS.

Algorithm

  1. Create two lists: sums to store the running sum at each level, and counts to store the number of nodes at each level.
  2. Run a DFS starting from the root at depth 0.
  3. At each node:
    • If the current depth equals the size of sums, this is the first time we have reached this depth. Append the node's value to sums and 1 to counts.
    • Otherwise, add the node's value to sums[depth] and increment counts[depth].
    • Recurse on the left child with depth + 1.
    • Recurse on the right child with depth + 1.
  4. After DFS completes, build the result by dividing sums[i] by counts[i] for each level.

Example Walkthrough

1Start DFS at root (3), depth=0
3depth=0920157
1/6
1Visit 3 at depth 0: sums[0] = 3
0
3
3
1/6
1Visit 3 at depth 0: counts[0] = 1
0
1
1
1/6

Code