Facebook Pixel

1742. Maximum Number of Balls in a Box

EasyHash TableMathCounting
Leetcode Link

Problem Description

You work at a ball factory with numbered balls ranging from lowLimit to highLimit (inclusive). The total number of balls is n = highLimit - lowLimit + 1. You also have an infinite supply of boxes numbered from 1 to infinity.

Your task is to place each ball into a specific box based on a simple rule: each ball goes into the box whose number equals the sum of the ball's digits. For instance:

  • Ball number 321 goes into box 3 + 2 + 1 = 6
  • Ball number 10 goes into box 1 + 0 = 1

After placing all balls from lowLimit to highLimit into their respective boxes according to this digit sum rule, you need to find which box contains the most balls and return that count.

The solution iterates through each ball number from lowLimit to highLimit, calculates the sum of its digits, and tracks how many balls end up in each box using an array. Since the maximum ball number is at most 10^5, the digit sum can never exceed 45 (which would be 99999), so an array of size 50 is sufficient to track all possible boxes. The algorithm then returns the maximum count found across all boxes.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is recognizing that we need to count how many balls go into each box, then find the maximum count. Since each ball's destination box is determined by its digit sum, we need to calculate the digit sum for every ball number in our range.

To approach this problem, let's first think about the constraints. What's the maximum possible digit sum we could encounter? Given that highLimit can be at most 10^5 (100,000), the largest digit sum would come from a number like 99,999, which gives us 9 + 9 + 9 + 9 + 9 = 45. This tells us we only need to track at most 46 different boxes (digit sums from 1 to 45).

This bounded range of possible digit sums is crucial - it means we can use a simple array to count occurrences rather than a more complex data structure like a hash map. We create an array cnt where cnt[i] represents how many balls are in box i.

The solution becomes straightforward:

  1. For each ball number from lowLimit to highLimit, calculate its digit sum
  2. Increment the counter for that digit sum (box number)
  3. After processing all balls, find the maximum value in our counter array

The digit sum calculation itself is a standard technique: repeatedly take the remainder when dividing by 10 (to get the last digit), add it to our sum, then integer divide by 10 (to remove the last digit). This process continues until the number becomes 0.

By tracking counts in an array and finding the maximum at the end, we efficiently solve the problem in linear time relative to the number of balls.

Learn more about Math patterns.

Solution Approach

The solution uses an array-based counting approach with digit sum calculation. Let's break down the implementation step by step:

1. Initialize the Counter Array

cnt = [0] * 50

We create an array of size 50 to count balls in each box. Since the maximum digit sum is less than 50 (as analyzed earlier), this array is sufficient to track all possible boxes.

2. Process Each Ball

for x in range(lowLimit, highLimit + 1):

We iterate through every ball number from lowLimit to highLimit inclusive.

3. Calculate Digit Sum For each ball number x, we calculate its digit sum using the standard digit extraction technique:

y = 0
while x:
    y += x % 10  # Extract the last digit and add to sum
    x //= 10     # Remove the last digit
  • x % 10 gives us the last digit of the number
  • x //= 10 performs integer division to remove the last digit
  • We repeat until x becomes 0, accumulating the sum in variable y

4. Update Box Count

cnt[y] += 1

Once we have the digit sum y, we increment the counter for box y, indicating one more ball has been placed in that box.

5. Find Maximum

return max(cnt)

After processing all balls, we return the maximum value in the cnt array, which represents the box with the most balls.

Time Complexity: O(n * d) where n = highLimit - lowLimit + 1 is the number of balls and d is the average number of digits per ball number.

Space Complexity: O(1) since the counter array has a fixed size of 50 regardless of input size.

The elegance of this solution lies in its simplicity - by recognizing the bounded nature of digit sums, we can use a fixed-size array for counting, making the implementation both efficient and straightforward.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example with lowLimit = 8 and highLimit = 13.

Step 1: Initialize counter array

cnt = [0, 0, 0, 0, 0, ...] (array of 50 zeros)

Step 2: Process each ball

Ball 8:

  • Calculate digit sum: 8 → digit sum = 8
  • Place in box 8: cnt[8] += 1
  • Counter state: cnt[8] = 1

Ball 9:

  • Calculate digit sum: 9 → digit sum = 9
  • Place in box 9: cnt[9] += 1
  • Counter state: cnt[9] = 1

Ball 10:

  • Calculate digit sum: 1 + 0 = 1
    • 10 % 10 = 0 (add 0 to sum)
    • 10 // 10 = 1
    • 1 % 10 = 1 (add 1 to sum)
    • 1 // 10 = 0 (stop)
  • Place in box 1: cnt[1] += 1
  • Counter state: cnt[1] = 1

Ball 11:

  • Calculate digit sum: 1 + 1 = 2
  • Place in box 2: cnt[2] += 1
  • Counter state: cnt[2] = 1

Ball 12:

  • Calculate digit sum: 1 + 2 = 3
  • Place in box 3: cnt[3] += 1
  • Counter state: cnt[3] = 1

Ball 13:

  • Calculate digit sum: 1 + 3 = 4
  • Place in box 4: cnt[4] += 1
  • Counter state: cnt[4] = 1

Step 3: Find maximum After processing all balls, our counter array has:

  • Box 1: 1 ball (ball 10)
  • Box 2: 1 ball (ball 11)
  • Box 3: 1 ball (ball 12)
  • Box 4: 1 ball (ball 13)
  • Box 8: 1 ball (ball 8)
  • Box 9: 1 ball (ball 9)
  • All other boxes: 0 balls

The maximum count is 1, so we return 1. In this case, all boxes that received balls have exactly 1 ball each.

For a more interesting example where boxes receive multiple balls, consider lowLimit = 19 and highLimit = 28:

  • Balls 19 and 28 both go to box 10 (1+9=10, 2+8=10)
  • Balls 20 and 29 would both go to box 2 and box 11 respectively if 29 were included
  • This would result in box 10 having 2 balls, making it the maximum

Solution Implementation

1class Solution:
2    def countBalls(self, lowLimit: int, highLimit: int) -> int:
3        # Initialize a counter array to store the count of balls in each box
4        # Maximum possible sum of digits for numbers up to 10^5 is 45 (99999)
5        # So 50 boxes are sufficient
6        box_counts = [0] * 50
7      
8        # Iterate through each ball number from lowLimit to highLimit (inclusive)
9        for ball_number in range(lowLimit, highLimit + 1):
10            # Calculate the sum of digits for current ball number
11            digit_sum = 0
12            temp_number = ball_number
13          
14            # Extract and sum each digit
15            while temp_number > 0:
16                digit_sum += temp_number % 10  # Get the last digit
17                temp_number //= 10  # Remove the last digit
18          
19            # Increment the count for the box corresponding to this digit sum
20            box_counts[digit_sum] += 1
21      
22        # Return the maximum count among all boxes
23        return max(box_counts)
24
1class Solution {
2    public int countBalls(int lowLimit, int highLimit) {
3        // Array to store count of balls in each box
4        // Maximum possible sum of digits is 45 (99999 = 9+9+9+9+9 = 45)
5        // So 50 boxes are sufficient
6        int[] boxCounts = new int[50];
7      
8        // Iterate through each ball number from lowLimit to highLimit
9        for (int ballNumber = lowLimit; ballNumber <= highLimit; ballNumber++) {
10            // Calculate the sum of digits for current ball number
11            int digitSum = 0;
12            int tempNumber = ballNumber;
13          
14            // Extract each digit and add to sum
15            while (tempNumber > 0) {
16                digitSum += tempNumber % 10;  // Get last digit
17                tempNumber /= 10;              // Remove last digit
18            }
19          
20            // Increment count for the box corresponding to this digit sum
21            boxCounts[digitSum]++;
22        }
23      
24        // Find and return the maximum count among all boxes
25        return Arrays.stream(boxCounts).max().getAsInt();
26    }
27}
28
1class Solution {
2public:
3    int countBalls(int lowLimit, int highLimit) {
4        // Array to store count of balls in each box
5        // Maximum possible sum is 9*5=45 (for 99999), so 50 is sufficient
6        int boxCount[50] = {0};
7      
8        // Variable to track the maximum number of balls in any box
9        int maxBallsInBox = 0;
10      
11        // Iterate through each ball number from lowLimit to highLimit
12        for (int ballNumber = lowLimit; ballNumber <= highLimit; ++ballNumber) {
13            // Calculate the sum of digits for current ball number
14            int digitSum = 0;
15            int tempNumber = ballNumber;
16          
17            // Extract and sum each digit
18            while (tempNumber > 0) {
19                digitSum += tempNumber % 10;  // Add the last digit
20                tempNumber /= 10;              // Remove the last digit
21            }
22          
23            // Increment the count for the box with index equal to digit sum
24            boxCount[digitSum]++;
25          
26            // Update the maximum count if current box has more balls
27            maxBallsInBox = max(maxBallsInBox, boxCount[digitSum]);
28        }
29      
30        // Return the maximum number of balls in any single box
31        return maxBallsInBox;
32    }
33};
34
1/**
2 * Counts the maximum number of balls in any box after distributing balls numbered from lowLimit to highLimit.
3 * Each ball is placed in a box where the box number equals the sum of the ball's digits.
4 * 
5 * @param lowLimit - The starting ball number (inclusive)
6 * @param highLimit - The ending ball number (inclusive)
7 * @returns The maximum number of balls in any single box
8 */
9function countBalls(lowLimit: number, highLimit: number): number {
10    // Initialize array to store count of balls in each box
11    // Maximum possible sum of digits for numbers up to 99999 is 45 (9+9+9+9+9)
12    const boxCounts: number[] = Array(50).fill(0);
13  
14    // Process each ball number from lowLimit to highLimit
15    for (let ballNumber = lowLimit; ballNumber <= highLimit; ballNumber++) {
16        // Calculate the sum of digits for current ball number
17        let digitSum = 0;
18        let tempNumber = ballNumber;
19      
20        // Extract and sum each digit
21        while (tempNumber > 0) {
22            digitSum += tempNumber % 10;  // Get the last digit
23            tempNumber = Math.floor(tempNumber / 10);  // Remove the last digit
24        }
25      
26        // Increment the count for the corresponding box
27        boxCounts[digitSum]++;
28    }
29  
30    // Return the maximum count among all boxes
31    return Math.max(...boxCounts);
32}
33

Time and Space Complexity

Time Complexity: O(n × log₁₀(m)), where n = highLimit - lowLimit + 1 represents the number of integers in the range, and m = highLimit represents the maximum value in the range.

  • The outer loop iterates through all integers from lowLimit to highLimit, which gives us n iterations.
  • For each integer x in this range, the inner while loop calculates the sum of its digits. The number of digits in an integer x is ⌊log₁₀(x)⌋ + 1, which is O(log₁₀(x)). In the worst case, when x = highLimit = m, this becomes O(log₁₀(m)).
  • Therefore, the total time complexity is O(n × log₁₀(m)).

Space Complexity: O(1)

  • The algorithm uses a fixed-size array cnt of length 50 to store the count of balls in each box. This size is constant regardless of the input values.
  • The maximum possible sum of digits occurs when all digits are 9. For a 32-bit integer (maximum value around 2×10⁹), the maximum sum would be 9×10 = 90, but the array size of 50 is sufficient for the problem constraints.
  • Additional variables x and y use constant space.
  • Since the space usage doesn't depend on the input size, the space complexity is O(1).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Modifying the Loop Variable While Calculating Digit Sum

One of the most common mistakes is directly modifying the loop variable when calculating the digit sum:

Incorrect Code:

for ball_number in range(lowLimit, highLimit + 1):
    digit_sum = 0
    # WRONG: This modifies ball_number directly!
    while ball_number > 0:
        digit_sum += ball_number % 10
        ball_number //= 10  # This destroys the original value
  
    box_counts[digit_sum] += 1  # ball_number is now 0, not the original value

Why it's wrong: After the first iteration, ball_number becomes 0, and the loop will not work correctly for subsequent iterations. The range loop expects ball_number to maintain its value through each iteration.

Correct Solution:

for ball_number in range(lowLimit, highLimit + 1):
    digit_sum = 0
    temp_number = ball_number  # Create a copy to work with
  
    while temp_number > 0:
        digit_sum += temp_number % 10
        temp_number //= 10  # Modify the copy, not the original
  
    box_counts[digit_sum] += 1

2. Incorrect Array Size Assumption

Another pitfall is using an array that's too small or making incorrect assumptions about the maximum digit sum:

Incorrect Code:

# WRONG: Assuming max digit sum is 9 (single digit)
box_counts = [0] * 10  

# Or WRONG: Using exact calculation but forgetting index starts at 0
box_counts = [0] * 45  # Will fail for digit sum of 45 (index out of bounds)

Correct Solution:

# Use a safely sized array that accounts for:
# - Maximum number 99999 has digit sum of 45
# - Array indices start at 0
# - Add some buffer for safety
box_counts = [0] * 50  # or even [0] * 46 would work

3. Alternative Correct Approach Using Dictionary

If you're unsure about the array size, using a dictionary eliminates this concern:

from collections import defaultdict

class Solution:
    def countBalls(self, lowLimit: int, highLimit: int) -> int:
        box_counts = defaultdict(int)
      
        for ball_number in range(lowLimit, highLimit + 1):
            digit_sum = 0
            temp_number = ball_number
          
            while temp_number > 0:
                digit_sum += temp_number % 10
                temp_number //= 10
          
            box_counts[digit_sum] += 1
      
        return max(box_counts.values())

This approach automatically handles any digit sum value without worrying about array bounds.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What data structure does Breadth-first search typically uses to store intermediate states?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More