root
of a binary tree, return the average value of the nodes on each level in the form of an array. Answers within 10-5
of the actual answer will be accepted.
Example 1:
Input: root = [3,9,20,null,null,15,7] Output: [3.00000,14.50000,11.00000] Explanation: The average value of nodes on level 0 is 3, on level 1 is 14.5, and on level 2 is 11. Hence return [3, 14.5, 11].
Example 2:
Input: root = [3,9,20,15,7] Output: [3.00000,14.50000,11.00000]
Constraints:
[1, 104]
.-231 <= Node.val <= 231 - 1
This problem asks to calculate the average value of nodes at each level of a binary tree. Two common approaches are Breadth-First Search (BFS) and Depth-First Search (DFS).
BFS is well-suited for level-order traversal. We use a queue to process nodes level by level.
Algorithm:
Initialization: Create a queue q
and add the root node. Initialize an empty list ans
to store the average of each level.
Level Processing: While the queue is not empty:
n
. This represents the number of nodes at the current level.s
(sum) to 0.n
nodes:
q
.s
.s / n
and append it to ans
.Return: Return ans
.
Time Complexity: O(N), where N is the number of nodes. Each node is visited and processed once. Space Complexity: O(W), where W is the maximum width (number of nodes) of the tree. In the worst case (a complete binary tree), W can be proportional to N.
DFS can also solve this, but requires a slightly different approach. We track the sum and count for each level separately.
Algorithm:
Initialization: Create two lists, s
(sum) and cnt
(count), both initially empty.
Recursive DFS: Implement a recursive function dfs(root, level)
:
root
is null, return.level
is beyond the size of s
and cnt
, append 0 to both lists to create a new entry for this level.root.val
to s[level]
and increment cnt[level]
.dfs
for the left and right children, incrementing the level.Average Calculation: After the DFS is complete, iterate through s
and cnt
, calculating the average s[i] / cnt[i]
for each level and storing it in the result list.
Time Complexity: O(N), where N is the number of nodes. Each node is visited once.
Space Complexity: O(H), where H is the height of the tree. This is due to the recursive call stack and the size of s
and cnt
which are proportional to the height of the tree. In the worst case (a skewed tree), H can be equal to N.
BFS:
from collections import deque
def averageOfLevels(root):
q = deque([root])
ans = []
while q:
level_size = len(q)
level_sum = 0
for _ in range(level_size):
node = q.popleft()
level_sum += node.val
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
ans.append(level_sum / level_size)
return ans
DFS:
def averageOfLevels(root):
sums = []
counts = []
def dfs(node, level):
if not node:
return
if level >= len(sums):
sums.append(0)
counts.append(0)
sums[level] += node.val
counts[level] += 1
dfs(node.left, level + 1)
dfs(node.right, level + 1)
dfs(root, 0)
return [s / c for s, c in zip(sums, counts)]
These examples demonstrate both approaches. The choice between BFS and DFS depends on factors like the specific tree structure and memory constraints. For most cases, BFS is generally preferred due to its better space complexity for balanced or nearly balanced trees.