Maximum Number of Balls in a Box
LeetCode 1742. Maximum Number of Balls in a Box gives you a ball factory with balls numbered from lowLimit to highLimit inclusive. Each ball goes into the box whose number equals the sum of the ball's digits. For example, ball 321 goes into box 6 because 3 + 2 + 1 = 6. Your job is to return the number of balls in the box that ends up with the most balls.
Why this problem matters
At first glance, this looks almost too simple to be worth studying. But it is a clean example of a pattern you will see constantly: transform a value, then count how many inputs produce the same transformed value. That is the core of frequency counting with a hash map. Once you internalize this pattern, problems like Group Anagrams, character frequency analysis, and bucket sort all feel familiar.
The key insight
Each ball number maps to a "bucket" determined by its digit sum. Two balls land in the same box if and only if they share the same digit sum. So the problem reduces to: compute a hash key (the digit sum) for every ball, count occurrences of each key, and return the maximum count.
This is the same idea behind any hash-based grouping. The digit sum is your hash function, and the boxes are your hash buckets.
The solution
def count_balls(low_limit: int, high_limit: int) -> int:
boxes = {}
for ball in range(low_limit, high_limit + 1):
digit_sum = sum(int(d) for d in str(ball))
boxes[digit_sum] = boxes.get(digit_sum, 0) + 1
return max(boxes.values())
How it works
The function iterates through every ball number from lowLimit to highLimit. For each number, it converts the number to a string, iterates over the characters, converts each back to an integer, and sums them up. That sum becomes the key in the boxes dictionary. The .get(digit_sum, 0) + 1 pattern increments the count for that box, defaulting to 0 if the box has not been seen yet. After processing all balls, max(boxes.values()) returns the largest count.
You could also compute the digit sum with modular arithmetic (divmod) instead of string conversion. Both approaches work fine for this problem since the numbers are small, but the divmod version avoids string allocation and is worth practicing as a standalone building block.
Visual walkthrough
Let's trace through the algorithm with lowLimit = 1 and highLimit = 10.
Step 1: Process balls 1 through 3
Single-digit balls each land in their own box. Every box has 1 ball so far.
Step 2: Process balls 4 through 6
Still single-digit numbers. Six boxes occupied, each with 1 ball.
Step 3: Process balls 7 through 9
Nine boxes now, each holding exactly 1 ball. No collisions yet.
Step 4: Process ball 10 (the interesting one)
Box 1 now holds 2 balls (ball 1 and ball 10). This is the first collision.
Step 5: Find the maximum
{1: 2, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}Box 1 has the most balls. Return 2.
Balls 1 through 9 each have a single-digit digit sum, so they go into separate boxes. Ball 10 has digits 1 and 0, giving a digit sum of 1, which means it shares box 1 with ball 1. The answer is 2.
Complexity analysis
| Aspect | Value |
|---|---|
| Time | O(n * d), where n = highLimit - lowLimit + 1 and d is the number of digits in each ball number |
| Space | O(k), where k is the number of distinct digit sums (at most 9 * d, which is small) |
The number of distinct digit sums is bounded. For numbers up to 100,000, the maximum digit sum is 9 * 5 = 45. So the hash map never holds more than about 45 entries regardless of input size. In practice, space is O(1) with respect to n.
Building blocks
This problem decomposes into two reusable pieces you will encounter in many other problems.
1. Digit sum computation
Extracting digits from a number and summing them is a micro-pattern that appears in problems like Happy Number and Add Digits. You can use string conversion or modular arithmetic.
def digit_sum(n: int) -> int:
total = 0
while n > 0:
n, digit = divmod(n, 10)
total += digit
return total
2. Frequency counting with a hash map
Counting how many items map to each category is one of the most common patterns in programming. You initialize a dictionary, iterate over your data, and increment counts.
counts = {}
for item in data:
key = transform(item)
counts[key] = counts.get(key, 0) + 1
This same pattern powers Group Anagrams, two-sum lookups, and dozens of other problems. On CodeBricks, you drill it until it becomes automatic.
Edge cases
- lowLimit equals highLimit: Only one ball exists. Every box has at most 1 ball, so return 1.
- All balls are single-digit: Each goes to a unique box (digit sums 1 through 9 are all different), so return 1.
- Large range with many collisions: For
lowLimit = 1andhighLimit = 1000000, many balls share the same digit sum. The algorithm handles this fine since the hash map stays small. - Ball number is a power of 10: Numbers like 10, 100, and 1000 all have digit sum 1. They all land in box 1 alongside ball 1.
- Consecutive multiples of 9: Numbers like 9, 18, 27, and 36 all have digit sum 9. If your range includes many of these, box 9 fills up quickly.
From understanding to recall
Reading this solution takes a minute. Reproducing it under interview pressure, two weeks from now, is a different challenge entirely.
That is what spaced repetition solves. CodeBricks breaks this problem into its two building blocks (digit sum computation and frequency counting) and drills them at increasing intervals. You type each piece from scratch, building real recall instead of vague familiarity. After a few review sessions, "compute a digit sum" and "count frequencies with a hash map" become reflexes.
Related posts
- Happy Number - Another digit manipulation problem that uses repeated digit extraction
- Add Digits - Computing digit sums repeatedly until a single digit remains
- Group Anagrams - Grouping items by a computed hash key, the same frequency counting pattern used here
One pattern, many problems
The transform-and-count pattern behind this problem is deceptively powerful. Once you can compute a key from your input and count frequencies in a hash map, you unlock solutions for grouping, deduplication, and mode-finding problems across many difficulty levels. Start with this easy problem, then notice how the same two building blocks appear in harder ones.