digit counting
integer range
algorithm
programming
computational methods

How to count each digit in a range of integers?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Counting how many times each digit appears in a range can be done by brute force, but that becomes slow for large intervals. A better approach uses positional counting: analyze the ones place, tens place, hundreds place, and so on, then combine those counts mathematically.

Brute force is correct but not scalable

The simple solution is:

  1. loop from a to b
  2. convert each number to digits
  3. update counters for 0 through 9

Example:

python
1def count_digits_bruteforce(a, b):
2    counts = [0] * 10
3    for n in range(a, b + 1):
4        for ch in str(n):
5            counts[int(ch)] += 1
6    return counts

This is fine for small ranges, but it costs roughly O((b - a + 1) * digits) operations. For very large ranges, you want something closer to O(log b).

Count digits from 0 to n position by position

The standard optimization counts how often each digit appears at each decimal position. For a position value factor = 1, 10, 100, ..., split n into:

  • 'higher = n // (factor * 10)'
  • 'current = (n // factor) % 10'
  • 'lower = n % factor'

Those three parts tell you how many full cycles and partial cycles the current digit position has completed.

A clean implementation for counting digit appearances from 0 to n can be written like this:

python
1def count_up_to(n):
2    if n < 0:
3        return [0] * 10
4
5    counts = [0] * 10
6    factor = 1
7
8    while factor <= n:
9        lower = n % factor
10        current = (n // factor) % 10
11        higher = n // (factor * 10)
12
13        for digit in range(10):
14            counts[digit] += higher * factor
15
16        for digit in range(current):
17            counts[digit] += factor
18
19        counts[current] += lower + 1
20
21        counts[0] -= factor
22        factor *= 10
23
24    counts[0] += 1
25    return counts

The counts[0] -= factor adjustment handles the fact that leading zeros should not be counted as visible digits.

Convert 0..n counting into range counting

Once you can count digits from 0 to n, a general inclusive range a..b is just:

python
1def count_digits_in_range(a, b):
2    if a > b:
3        a, b = b, a
4
5    high = count_up_to(b)
6    low = count_up_to(a - 1)
7    return [h - l for h, l in zip(high, low)]

Now:

python
print(count_digits_in_range(1, 20))

returns the counts for all digits in that interval without iterating over every number one by one.

Why the positional method works

At each position, digits repeat in regular cycles.

For the ones place:

  • every block of 10 numbers contains each digit once

For the tens place:

  • every block of 100 numbers contains each digit in that position for 10 consecutive values

For the hundreds place:

  • every block of 1000 numbers contains each digit in that position for 100 consecutive values

The algorithm exploits those cycles instead of enumerating every number.

Common Pitfalls

The biggest mistake is mishandling zeros. Leading zeros are not part of the written representation of ordinary integers, so they need special correction in the positional formula.

Another mistake is forgetting that range counting should usually be inclusive. If the task says "from a to b," make sure both endpoints are handled consistently.

Developers also assume brute force is good enough until the input becomes huge. For interview-style or algorithmic versions of this problem, the positional method is usually what is expected.

Finally, be careful when the range includes negative numbers. The standard digit-counting formulas are usually defined for non-negative integer representations.

Summary

  • Brute force counting is easy to write but too slow for large ranges.
  • The efficient solution counts digit contributions position by position.
  • A helper for 0..n can be turned into range counting by subtraction.
  • Zero needs special handling because leading zeros should not be counted.
  • Positional analysis reduces the problem from scanning every number to analyzing decimal cycles.

Course illustration
Course illustration

All Rights Reserved.