🪙
Leetcode
  • Content
  • Algorithms
    • Linear Search
    • Binary Search
    • Counting Sort
    • Merge Sort
    • Insertion Sort
    • Selection Sort
  • Array and String
    • Introduction to Array
      • Introduction to Array
      • Introduction to Dynamic Array
      • Find Pivot Index
      • Largest Number At Least Twice of Others
      • Plus One
    • Introduction to 2D Array
      • Introduction to 2D Array
      • Diagonal Traverse
      • Spiral Matrix
      • Pascal's Triangle
    • Introduction to String
      • Introduction to String
      • Immutable String - Problems & Solutions
      • Add binary
      • Implement strStr()
      • Longest Common Prefix
    • Two-Pointer Technique
      • Two-pointer Technique - Scenario I
      • Reverse String
      • Array Partition I
      • Two Sum II - Input array is sorted
      • Two-pointer Technique - Scenario II
      • Remove Element
      • Max Consecutive Ones
      • Minimum Size Subarray Sum
    • Conclusion
      • Array-related Techniques
      • Rotate Array
      • Pascal's Triangle II
      • Reverse Words in a String
      • Reverse Words in a String III
      • Remove Duplicates from Sorted Array
      • Move Zeroes
  • Linked List
    • Singly Linked List
      • Introduction - Singly Linked List
      • Add Operation - Singly Linked List
      • Delete Operation - Singly Linked List
      • Design Linked List
    • Two Pointer Technique
      • Two-Pointer in Linked List
      • Linked List Cycle
      • Linked List Cycle II
      • Intersection of Two Linked Lists
      • Remove Nth Node From End of List
      • Summary - Two-Pointer in Linked List
  • Problems
    • 1. Two Sum
    • 2. Add Two Numbers
    • 7. Reverse Integer
    • 9. Palindrome Number
    • 11. Container With Most Water
    • 12. Integer to Roman
    • 13. Roman to Integer
    • 14. Longest Common Prefix
    • 15. 3Sum
    • 21. Merge Two Sorted Lists
    • 26. Remove Duplicates from Sorted Array
    • 27. Remove Element
    • 28. Find the Index of the First Occurrence in a String
    • 34. Find First and Last Position of Element in Sorted Array
    • 35. Search Insert Position
    • 43. Multiply Strings
    • 49. Group Anagrams
    • 50. Pow(x, n)
    • 54. Spiral Matrix
    • 58. Length of Last Word
    • 66. Plus One
    • 67. Add Binary
    • 69. Sqrt(x)
    • 73. Set Matrix Zeroes
    • 75. Sort Colors
    • 88. Merge Sorted Array
    • 104. Maximum Depth of Binary Tree
    • 121. Best Time to Buy and Sell Stock
    • 122. Best Time to Buy and Sell Stock II
    • 136. Single Number
    • 146. LRU Cache
    • 189. Rotate Array
    • 206. Reverse Linked List
    • 217. Contains Duplicate
    • 219. Cotains Duplicate II
    • 226. Invert Binary Tree
    • 238. Product of Array Except Self
    • 242. Valid Anagram
    • 268. Missing Number
    • 283. Move Zeroes
    • 350. Intersection of Two Arrays II
    • 383. Ransom Note
    • 389. Find the Difference
    • 412. Fizz Buzz
    • 414. Third Maximum Number
    • 445. Add Two Numbers II
    • 448. Find All Numbers Disappeared in an Array
    • 459. Repeated Substring Pattern
    • 485. Max Consecutive Ones
    • 509. Fibonacci Number
    • 637. Average of Levels in Binary Tree
    • 657. Robot Return to Origin
    • 682. Baseball Game
    • 704. Binary Search
    • 705. Design HashSet
    • 709. To Lower Case
    • 724. Find Pivot Index
    • 876. Middle of the Linked List
    • 896. Monotonic Array
    • 860. Lemonade Change
    • 905. Sort Array By Parity
    • 916. Word Subsets
    • 941. Valid Mountain Array
    • 976. Largest Perimeter Triangle
    • 977. Squares of a Sorted Array
    • 1041. Robot Bounded In Circle
    • 1051. Height Checker
    • 1089. Duplicate Zeros
    • 1232. Check If It Is a Straight Line
    • 1275. Find Winner on a Tic Tac Toe Game
    • 1295. Find Numbers with Even Number of Digits
    • 1299. Replace Elements with Greatest Element on Right Side
    • 1342. Number of Steps to Reduce a Number to Zero
    • 1346. Check If N and Its Double Exist
    • 1476. Subrectangle Queries
    • 1480. Running Sum of 1d Array
    • 1491. Average Salary Excluding the Minimum and Maximum Salary
    • 1502. Can Make Arithmetic Progression From Sequence
    • 1523. Count Odd Numbers in an Interval Range
    • 1572. Matrix Diagonal Sum
    • 1672. Richest Customer Wealth
    • 1768. Merge Strings Alternately
    • 1752. Check if Array Is Sorted and Rotated
    • 1769. Minimum Number of Operations to Move All Balls to Each Box
    • 1790. Check if One String Swap Can Make Strings Equal
    • 1800. Maximum Ascending Subarray Sum
    • 1822. Sign of the Product of an Array
    • 1930. Unique Length-3 Palindromic Subsequences
    • 1991. Find the Middle Index in Array
    • 2185. Counting Words With a Given Prefix
    • 2235. Add Two Integers
    • 2236. Root Equals Sum of Children
    • 2270. Number of Ways to Split Array
    • 2381. Shifting Letters II
    • 2559. Count Vowel Strings in Ranges
    • 2610. Convert an Array Into a 2D Array With Conditions
    • 2657. Find the Prefix Common Array of Two Arrays
    • 3042. Count Prefix and Suffix Pairs I
    • 3105. Longest Strictly Increasing or Strictly Decreasing Subarray
    • 3151. Special Array I
    • 3223. Minimum Length of String After Operations
Powered by GitBook
On this page
  • Example 1
  • Example 2
  • Constraints
  • Solution
  • Optimal Solution
  • Approach Analysis
  • Visualization of Both Approaches
  • Complexity Analysis
  • Why Solution Works
  • When to Use
  • Common Patterns & Applications
  • Interview Tips

Was this helpful?

Edit on GitHub
  1. Problems

637. Average of Levels in Binary Tree

Previous509. Fibonacci NumberNext657. Robot Return to Origin

Last updated 5 months ago

Was this helpful?

Easy

Given the 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

tree

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

  • The number of nodes in the tree is in the range [1, 10^4].

  • -2^31 <= Node.val <= 2^31 - 1

Solution

My Solution

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func averageOfLevels(root *TreeNode) []float64 {
    resp := []float64{}

    queue := []*TreeNode{root}

    for len(queue) != 0 {
        size := len(queue)
        level := 0

        for i:=0; i < size; i++ {
            level += queue[i].Val

            if queue[i].Left != nil {
                queue = append(queue, queue[i].Left)
            }

            if queue[i].Right != nil {
                queue = append(queue, queue[i].Right)
            }
        }

        queue = queue[size:]
        resp = append(resp, float64(level)/float64(size))
    }

    return resp
}

Optimal Solution

The optimal solution uses level-order traversal (BFS) with two key improvements:

  1. Using int64 to handle potential integer overflow

  2. Pre-allocating the result slice for better performance

  3. Efficient queue management with slice operations

func averageOfLevels(root *TreeNode) []float64 {
    if root == nil {
        return nil
    }
    
    // Pre-allocate result slice (optimization)
    result := make([]float64, 0, 10000) // max nodes = 10^4
    
    // Initialize queue with root
    queue := []*TreeNode{root}
    
    for len(queue) > 0 {
        levelSize := len(queue)
        levelSum := int64(0) // Use int64 to prevent overflow
        
        // Process current level
        for i := 0; i < levelSize; i++ {
            node := queue[0]
            queue = queue[1:] // More efficient queue management
            
            levelSum += int64(node.Val)
            
            // Add children to queue
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        
        // Calculate and store average
        avg := float64(levelSum) / float64(levelSize)
        result = append(result, avg)
    }
    
    return result
}

Approach Analysis

The solution employs two main techniques:

  1. Level-Order Traversal (BFS):

    • Uses queue data structure

    • Processes nodes level by level

    • Maintains level boundaries

    • Ensures correct level averages

  2. Efficient Memory Management:

    • Pre-allocated result slice

    • Optimized queue operations

    • Integer overflow prevention

    • Proper type conversions

Visualization of Both Approaches

Example Tree:
     3
   /   \
  9    20
      /  \
     15   7

BFS Traversal Steps:

Level 0: [3]
Queue: [3]
Sum: 3
Average: 3.0

Level 1: [9, 20]
Queue: [9, 20]
Sum: 29
Average: 14.5

Level 2: [15, 7]
Queue: [15, 7]
Sum: 22
Average: 11.0

Final Result: [3.0, 14.5, 11.0]

Complexity Analysis

Time Complexity:

  • O(n) - visit each node exactly once

  • O(1) - queue operations (append/remove)

  • O(1) - average calculation per level

  • Total: O(n) where n is number of nodes

Space Complexity:

  • O(w) - queue size (w = max width of tree)

  • O(h) - result array (h = height of tree)

  • Total: O(w) where w is maximum width

Optimizations:

  • Pre-allocated result slice

  • int64 for overflow prevention

  • Efficient queue management

  • Early nil check

Why Solution Works

  1. BFS Properties:

    • Natural level-by-level traversal

    • Maintains level boundaries

    • Complete level processing

    • Correct order guarantee

  2. Memory Management:

    • Efficient slice operations

    • No extra data structures

    • Minimal memory overhead

    • Prevents integer overflow

  3. Average Calculation:

    • Accurate level tracking

    • Proper type handling

    • Precision maintenance

    • Overflow prevention

When to Use

This approach is ideal when:

  1. Need level-by-level tree processing

  2. Require level-based calculations

  3. Memory can handle tree width

  4. Order within levels doesn't matter

Common applications:

  • Level-order tree traversal

  • Level statistics calculation

  • Tree visualization

  • Level-based tree operations

Common Patterns & Applications

  1. BFS Pattern:

    • Queue-based traversal

    • Level-by-level processing

    • Width-first exploration

    • Level boundary tracking

  2. Tree Level Processing:

    • Level statistics

    • Level modifications

    • Level grouping

    • Level comparisons

  3. Average Calculations:

    • Numeric overflow handling

    • Floating-point precision

    • Group-based statistics

    • Level-based metrics

Interview Tips

  1. Initial Clarification:

    • Confirm if we need to handle empty tree

    • Ask about precision requirements for averages

    • Clarify if the order of nodes within levels matters

    • Discuss memory constraints for large trees

  2. Solution Walkthrough:

    • Start with BFS approach explanation

    • Mention queue usage for level tracking

    • Explain why BFS is better than DFS here

    • Discuss integer overflow prevention

  3. Code Implementation Strategy:

    • Begin with basic queue structure

    • Add level size tracking

    • Implement sum calculation with overflow prevention

    • Handle edge cases last

  4. Optimization Discussion:

    • Pre-allocate slices for better performance

    • Use int64 for sum to prevent overflow

    • Efficient queue management with slice operations

    • Early termination for nil root

  5. Common Pitfalls to Avoid:

    • Integer overflow with large numbers

    • Not tracking level boundaries correctly

    • Inefficient queue operations

    • Missing edge cases

  6. Follow-up Questions:

    • Q: "How would you handle a very wide tree?" A: Use level-by-level processing to limit memory usage

    • Q: "Can we solve this using DFS?" A: Yes, using a map to track level sums and counts

    • Q: "How to optimize memory usage?" A: Process nodes level by level, reuse queue space

    • Q: "What if we need exact decimal precision?" A: Use big.Float or similar for precise calculations

  7. Edge Cases to Test:

    • Empty tree: return empty slice

    • Single node: return [node.Val]

    • Complete binary tree: maximum width

    • Skewed tree: minimal width

    • Large values: potential overflow

  8. Code Quality Points:

    • Clear variable names (levelSize, levelSum)

    • Proper type conversions

    • Early return for nil

    • Clean queue management

    • Consistent error handling

  9. Alternative Approaches:

    • DFS with level tracking

    • Iterative vs recursive

    • Array-based complete tree

    • Morris traversal variation

  10. Performance Analysis:

    • Time: O(n) - visit each node once

    • Space: O(w) - w is max tree width

    • Memory-time tradeoffs

    • Optimization possibilities

tree_2

Leetcode:

link
result