Facebook Pixel

1399. Count Largest Group

EasyHash TableMath
Leetcode Link

Problem Description

You need to group all integers from 1 to n based on their digit sum. Two numbers belong to the same group if the sum of their digits is equal.

For example:

  • The number 14 has digit sum 1 + 4 = 5

  • The number 5 has digit sum 5

  • So 14 and 5 belong to the same group (both have digit sum of 5)

  • The number 13 has digit sum 1 + 3 = 4

  • The number 3 has digit sum 3

  • So 13 and 3 belong to different groups (digit sums of 4 and 3 respectively)

After grouping all numbers from 1 to n by their digit sums, you need to find the size of the largest group(s). Then return how many groups have this maximum size.

For instance, if after grouping you have:

  • Group with digit sum 3: contains 2 numbers
  • Group with digit sum 4: contains 3 numbers
  • Group with digit sum 5: contains 3 numbers
  • Group with digit sum 6: contains 1 number

The maximum group size is 3, and there are 2 groups with this size (digit sums 4 and 5), so the answer would be 2.

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

Intuition

The key insight is that we need to track two things: the size of each group and which group size is the largest.

Since we're grouping numbers by their digit sum, we can use the digit sum as a key to count how many numbers fall into each group. For any number from 1 to n, we can calculate its digit sum by repeatedly taking the remainder when divided by 10 (to get the last digit) and then dividing by 10 (to remove the last digit).

As we process each number from 1 to n, we calculate its digit sum and increment the count for that particular sum. This naturally builds up our groups.

The clever part is tracking the answer as we go. Instead of first building all groups and then finding the maximum size and counting how many groups have that size, we can do it in one pass:

  • Whenever we encounter a group that becomes larger than our current maximum size, we know this is now the only group with the maximum size, so we reset our answer to 1
  • Whenever we encounter a group that equals our current maximum size, we've found another group with the maximum size, so we increment our answer

This way, by the time we've processed all numbers from 1 to n, we already have our answer without needing a second pass through the data.

The constraint that n ≤ 10^4 tells us the maximum possible digit sum is 9 + 9 + 9 + 9 = 36 (for 9999), so we know our groups are limited to at most 36 different digit sums, making this approach very efficient.

Learn more about Math patterns.

Solution Approach

We implement the solution using a hash table (or array) to count occurrences of each digit sum.

Data Structure Setup:

  • Create a counter cnt to track how many numbers have each digit sum
  • Initialize variables mx = 0 to track the maximum group size and ans = 0 to count groups with maximum size

Main Algorithm:

For each number i from 1 to n:

  1. Calculate digit sum:

    • Initialize s = 0 to store the sum
    • While i > 0:
      • Add the last digit to sum: s += i % 10
      • Remove the last digit: i //= 10
  2. Update the count for this digit sum:

    • Increment cnt[s] by 1
  3. Update the answer based on the new count:

    • If cnt[s] > mx: We found a new maximum group size
      • Update mx = cnt[s]
      • Reset ans = 1 (only one group has this new maximum size)
    • Else if cnt[s] == mx: We found another group with the maximum size
      • Increment ans += 1

Why this works:

  • Since we know the maximum digit sum is 36 (from 9999), we could alternatively use an array of size 40 instead of a hash table
  • By tracking mx and ans during the iteration, we avoid a second pass through the data
  • The counter naturally groups numbers by their digit sum as we process them

Time Complexity: O(n × log n) where the log n factor comes from calculating the digit sum of each number (number of digits is proportional to log n)

Space Complexity: O(1) since we're storing at most 36 different digit sums

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 the solution with n = 15.

Initial Setup:

  • cnt = {} (empty counter for digit sums)
  • mx = 0 (maximum group size)
  • ans = 0 (count of groups with maximum size)

Processing each number from 1 to 15:

iDigit Sum Calculationscnt[s]mxansExplanation
111111New max size, reset ans to 1
222112Equals max, increment ans
333113Equals max, increment ans
444114Equals max, increment ans
555115Equals max, increment ans
666116Equals max, increment ans
777117Equals max, increment ans
888118Equals max, increment ans
999119Equals max, increment ans
101+0 = 11221New max size, reset ans to 1
111+1 = 22222Equals max, increment ans
121+2 = 33223Equals max, increment ans
131+3 = 44224Equals max, increment ans
141+4 = 55225Equals max, increment ans
151+5 = 66226Equals max, increment ans

Final Groups:

  • Digit sum 1: {1, 10} → size 2
  • Digit sum 2: {2, 11} → size 2
  • Digit sum 3: {3, 12} → size 2
  • Digit sum 4: {4, 13} → size 2
  • Digit sum 5: {5, 14} → size 2
  • Digit sum 6: {6, 15} → size 2
  • Digit sum 7: {7} → size 1
  • Digit sum 8: {8} → size 1
  • Digit sum 9: {9} → size 1

Result: Maximum group size is 2, and there are 6 groups with this size, so the answer is 6.

The key insight demonstrated here is how we dynamically track the answer:

  • When we hit number 10, it creates the first group of size 2 (digit sum 1), making it the new maximum
  • As we continue, numbers 11-15 each create groups of size 2, incrementing our answer each time
  • We never need to look back at our groups - the answer is computed on the fly

Solution Implementation

1from collections import Counter
2
3class Solution:
4    def countLargestGroup(self, n: int) -> int:
5        # Dictionary to count frequency of each digit sum
6        digit_sum_count = Counter()
7        # Track the maximum group size and count of groups with that size
8        num_largest_groups = 0
9        max_group_size = 0
10      
11        # Iterate through all numbers from 1 to n
12        for number in range(1, n + 1):
13            # Calculate sum of digits for current number
14            digit_sum = 0
15            temp = number
16            while temp > 0:
17                digit_sum += temp % 10  # Add the last digit
18                temp //= 10  # Remove the last digit
19          
20            # Increment count for this digit sum
21            digit_sum_count[digit_sum] += 1
22          
23            # Update tracking variables
24            if digit_sum_count[digit_sum] > max_group_size:
25                # Found a new maximum group size
26                max_group_size = digit_sum_count[digit_sum]
27                num_largest_groups = 1
28            elif digit_sum_count[digit_sum] == max_group_size:
29                # Found another group with the same maximum size
30                num_largest_groups += 1
31      
32        return num_largest_groups
33
1class Solution {
2    public int countLargestGroup(int n) {
3        // Array to store count of numbers for each possible digit sum
4        // Maximum digit sum for n <= 10^4 is 9+9+9+9 = 36, so size 40 is sufficient
5        int[] digitSumCount = new int[40];
6      
7        // Track the count of groups with maximum size
8        int largestGroupCount = 0;
9        // Track the maximum group size found so far
10        int maxGroupSize = 0;
11      
12        // Iterate through all numbers from 1 to n
13        for (int currentNumber = 1; currentNumber <= n; ++currentNumber) {
14            // Calculate the sum of digits for current number
15            int digitSum = 0;
16            for (int temp = currentNumber; temp > 0; temp /= 10) {
17                digitSum += temp % 10;  // Extract and add the last digit
18            }
19          
20            // Increment the count for this digit sum
21            ++digitSumCount[digitSum];
22          
23            // Check if we found a new maximum group size
24            if (maxGroupSize < digitSumCount[digitSum]) {
25                maxGroupSize = digitSumCount[digitSum];
26                largestGroupCount = 1;  // Reset count to 1 for new maximum
27            } else if (maxGroupSize == digitSumCount[digitSum]) {
28                // Found another group with the same maximum size
29                ++largestGroupCount;
30            }
31        }
32      
33        return largestGroupCount;
34    }
35}
36
1class Solution {
2public:
3    int countLargestGroup(int n) {
4        // Array to count the frequency of each digit sum
5        // Maximum possible sum is 9*4=36 for n=9999 (max n is 10^4)
6        int digitSumFrequency[40]{};
7      
8        // Track the count of groups with maximum size
9        int largestGroupCount = 0;
10        // Track the maximum group size seen so far
11        int maxGroupSize = 0;
12      
13        // Iterate through all numbers from 1 to n
14        for (int number = 1; number <= n; ++number) {
15            // Calculate the sum of digits for current number
16            int digitSum = 0;
17            for (int temp = number; temp > 0; temp /= 10) {
18                digitSum += temp % 10;  // Extract and add the last digit
19            }
20          
21            // Increment the frequency count for this digit sum
22            ++digitSumFrequency[digitSum];
23          
24            // Check if we found a new maximum group size
25            if (maxGroupSize < digitSumFrequency[digitSum]) {
26                maxGroupSize = digitSumFrequency[digitSum];
27                largestGroupCount = 1;  // Reset count to 1 for new maximum
28            } 
29            // Check if current group size equals the maximum
30            else if (maxGroupSize == digitSumFrequency[digitSum]) {
31                ++largestGroupCount;  // Increment count of largest groups
32            }
33        }
34      
35        return largestGroupCount;
36    }
37};
38
1/**
2 * Counts the number of groups that have the maximum size when grouping numbers by their digit sum
3 * @param n - The upper bound of the range [1, n] to check
4 * @returns The count of groups with the maximum size
5 */
6function countLargestGroup(n: number): number {
7    // Array to store count of numbers for each possible digit sum
8    // Maximum possible sum is 9*4 = 36 (for 9999), so 40 is sufficient
9    const digitSumCounts: number[] = Array(40).fill(0);
10  
11    // Track the maximum group size found
12    let maxGroupSize: number = 0;
13  
14    // Count of groups that have the maximum size
15    let groupsWithMaxSize: number = 0;
16  
17    // Iterate through all numbers from 1 to n
18    for (let currentNumber: number = 1; currentNumber <= n; ++currentNumber) {
19        // Calculate the sum of digits for the current number
20        let digitSum: number = 0;
21        let tempNumber: number = currentNumber;
22      
23        // Extract and sum each digit
24        while (tempNumber > 0) {
25            digitSum += tempNumber % 10;
26            tempNumber = Math.floor(tempNumber / 10);
27        }
28      
29        // Increment the count for this digit sum
30        ++digitSumCounts[digitSum];
31      
32        // Check if we found a new maximum group size
33        if (maxGroupSize < digitSumCounts[digitSum]) {
34            maxGroupSize = digitSumCounts[digitSum];
35            groupsWithMaxSize = 1;  // Reset count to 1 for the new maximum
36        } else if (maxGroupSize === digitSumCounts[digitSum]) {
37            // Found another group with the same maximum size
38            ++groupsWithMaxSize;
39        }
40    }
41  
42    return groupsWithMaxSize;
43}
44

Time and Space Complexity

Time Complexity: O(n × log n)

The algorithm iterates through all numbers from 1 to n, which takes O(n) iterations. For each number i, we calculate the sum of its digits by repeatedly dividing by 10 and taking the remainder. The number of digits in a number i is approximately log₁₀(i), so extracting all digits takes O(log i) time. In the worst case when i = n, this becomes O(log n). Therefore, the overall time complexity is O(n × log n).

Space Complexity: O(log n)

The space is primarily used by the Counter dictionary cnt. The key insight is that the dictionary stores digit sums as keys. The maximum possible digit sum occurs for the number n, and since n has at most O(log n) digits, and each digit can be at most 9, the maximum possible sum is 9 × O(log n) = O(log n). The number of unique digit sums is bounded by this maximum value, so the dictionary can have at most O(log n) entries. Therefore, the space complexity is O(log n).

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

Common Pitfalls

1. Modifying the Loop Variable While Calculating Digit Sum

A common mistake is directly modifying the loop variable i when calculating the digit sum:

Incorrect Code:

for i in range(1, n + 1):
    digit_sum = 0
    while i > 0:  # BUG: Modifying loop variable i
        digit_sum += i % 10
        i //= 10  # This destroys the original value of i
  
    # Now i is 0, not the original number!
    digit_sum_count[digit_sum] += 1

Why it's wrong: After calculating the digit sum, i becomes 0, so you lose track of which number you were processing. This breaks the loop iteration.

Solution: Always use a temporary variable to preserve the original value:

for i in range(1, n + 1):
    digit_sum = 0
    temp = i  # Create a copy
    while temp > 0:
        digit_sum += temp % 10
        temp //= 10
  
    # i is still intact
    digit_sum_count[digit_sum] += 1

2. Incorrect Answer Tracking Logic

Another pitfall is resetting the counter at the wrong time or not handling the first occurrence correctly:

Incorrect Code:

if digit_sum_count[digit_sum] >= max_group_size:  # BUG: Using >= instead of >
    max_group_size = digit_sum_count[digit_sum]
    num_largest_groups = 1  # This resets even when equal!

Why it's wrong: Using >= would reset the counter every time we see a group with the current maximum size, losing count of previous groups with the same size.

Solution: Use strict comparison operators correctly:

if digit_sum_count[digit_sum] > max_group_size:
    # New maximum found
    max_group_size = digit_sum_count[digit_sum]
    num_largest_groups = 1
elif digit_sum_count[digit_sum] == max_group_size:
    # Another group with same maximum size
    num_largest_groups += 1

3. Post-Processing Instead of Real-Time Tracking

Some might try to find the answer after building the complete frequency map:

Less Efficient Approach:

# Build complete frequency map first
for i in range(1, n + 1):
    digit_sum = calculate_digit_sum(i)
    digit_sum_count[digit_sum] += 1

# Then find the answer (requires second pass)
max_size = max(digit_sum_count.values())
return sum(1 for count in digit_sum_count.values() if count == max_size)

Why it's suboptimal: This requires two passes through the data - one to build the map and another to find the answer.

Solution: Track the answer while building the frequency map (as shown in the original solution), which requires only one pass and is more efficient.

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

Which of the tree traversal order can be used to obtain elements in a binary search tree in sorted order?


Recommended Readings

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

Load More