AlgoMaster Logo

Numbers At Most N Given Digit Set

Last Updated: March 28, 2026

hard
5 min read

Understanding the Problem

We are given a set of allowed digits (each between '1' and '9'), and we need to count how many positive integers up to n can be formed using only those digits. Each digit can be reused as many times as we want. So if digits = ["1","3"], we can form 1, 3, 11, 13, 31, 33, 111, 113, and so on.

The key insight is that this is really a counting problem with two distinct parts. First, any number with fewer digits than n is automatically less than n, so we can count all of those easily. Second, for numbers with the same number of digits as n, we need to carefully count only those that do not exceed n. This second part is where the problem gets interesting, and it is a classic application of digit dynamic programming.

Key Constraints:

  • 1 <= n <= 10^9 → n has at most 10 digits. Any approach that processes digit-by-digit is very efficient.
  • 1 <= digits.length <= 9 → The digit set is small. We can iterate over it freely at each position.
  • digits[i] is from '1' to '9' → No zero in the digit set. This simplifies things because every combination of allowed digits forms a valid positive integer (no leading zero issues).

Approach 1: Brute Force (Enumerate All Numbers)

Intuition

The simplest approach is to generate every possible number from the allowed digits and check if it is at most n. We can do this with BFS: start with each allowed digit, then repeatedly append allowed digits to build longer numbers.

This is straightforward but extremely slow for large n. If digits = ["1","3","5","7"] and n = 10^9, we could potentially generate millions of numbers.

Algorithm

  1. Start a counter at 0.
  2. Use a queue to generate numbers starting from each digit in the set.
  3. For each generated number, if it is at most n, increment the counter and try appending each allowed digit to generate longer numbers.
  4. If a number exceeds n, stop expanding from it.
  5. Return the counter.

Code

This approach generates every valid number, which is far too slow for large inputs. Instead of enumerating, can we count valid numbers mathematically?

Approach 2: Math (Counting by Number of Digits)

Intuition

Instead of generating numbers one by one, we can count them mathematically. The key observation splits the problem into two parts.

Part 1: Numbers with fewer digits than n. If n has L digits, then any valid number with 1 digit, 2 digits, ..., or L-1 digits is automatically less than n. For k-digit numbers, each of the k positions can be any of the d allowed digits (since none of them is '0', there is no leading-zero issue). So there are d^k valid numbers of exactly k digits.

Part 2: Numbers with exactly L digits. We process the digits of n from left to right. At each position i, we ask: how many allowed digits are strictly less than n's digit at position i? Each of those lets us fill the remaining positions freely. Is n's digit at position i itself in the allowed set? If yes, we match it and continue. If no, we stop.

If we successfully match every digit of n, then n itself is a valid number, so we add 1.

Algorithm

  1. Convert n to a string S of length L. Let d = digits.length.
  2. Initialize count = 0.
  3. For k from 1 to L-1, add d^k to count. These are all valid numbers shorter than n.
  4. For each position i from 0 to L-1:
    • Count how many digits in the allowed set are strictly less than S[i]. Call this less.
    • Add less * d^(L-1-i) to count.
    • If S[i] is not in the allowed set, stop.
    • If S[i] is in the allowed set, continue to the next position.
  5. If we processed all L positions without stopping, add 1 (the number n itself is valid).
  6. Return count.

Example Walkthrough

1n=100, S="100", L=3, d=4, digits={1,3,5,7}
0
1
1
0
2
0
1/7

Code

This approach uses floating-point Math.pow which can cause precision issues. Can we precompute powers with integer arithmetic and express the solution as a clean DP?

Approach 3: Digit DP (Optimal)

Intuition

We can reformulate this as a dynamic programming problem that processes n from right to left. Define dp[i] as the number of valid numbers that can be formed considering positions i through L-1 of n, under the constraint that the prefix so far exactly matches n.

The recurrence works as follows: for each allowed digit less than S[i], we can fill the remaining positions freely (contributing d^(L-1-i)). For each allowed digit equal to S[i], the answer depends on dp[i+1]. Digits greater than S[i] contribute nothing.

The base case is dp[L] = 1, meaning if we have matched all digits of n exactly, we count n itself. We still add the counts for numbers shorter than n separately.

Algorithm

  1. Convert n to string S of length L. Let d = digits.length.
  2. Precompute powers: pow[i] = d^i for i from 0 to L using integer arithmetic.
  3. Compute dp from right to left:
    • dp[L] = 1 (base case: matched all digits of n).
    • For i from L-1 down to 0:
      • For each allowed digit less than S[i]: add pow[L-1-i].
      • For each allowed digit equal to S[i]: add dp[i+1].
  4. The answer for same-length numbers is dp[0].
  5. Add shorter numbers: sum of pow[1] through pow[L-1].
  6. Return the total.

Example Walkthrough

1S="573", L=3, d=4. Initialize dp[3]=1 (base case: matched all digits)
0
0
1
0
2
0
3
1
base
1/6

Code