Sequential Digits: Generating Numbers with Consecutive Digits
LeetCode 1291. Sequential Digits gives you two integers low and high and asks you to return a sorted list of all sequential digits numbers in the range [low, high]. A sequential digit number is one where each digit is exactly one more than the digit before it. For example, 123 is sequential (1, 2, 3), but 135 is not (the gap between 1 and 3 is 2, not 1).
Why this problem is easier than it looks
Your first instinct might be to iterate through every number from low to high and check whether it has the sequential digits property. That would work, but it is way more work than necessary. The range could be enormous (up to 10^9), so brute force is out.
The key insight is that there are very few sequential digit numbers in total. Think about it: a sequential digit number is completely determined by its starting digit and its length. The starting digit can be 1 through 9, and the length can be 2 through 9. But not all combinations are valid. If you start at 8 with length 3, you would need digits 8, 9, 10, and 10 is not a single digit. So the starting digit is bounded by 9 - length + 1.
When you count them all up, there are exactly 36 sequential digit numbers in existence. You can generate every single one and then just filter by the range.
The approach
The plan is clean:
- Loop over every possible length from 2 to 9.
- For each length, loop over every valid starting digit (1 through
9 - length + 1). - Build the number by appending consecutive digits.
- If the number falls within
[low, high], add it to the result.
Because you iterate lengths from small to large and starting digits from small to large, the output is automatically sorted. No extra sorting step needed.
def sequential_digits(low: int, high: int) -> list[int]:
results = []
for length in range(2, 10):
for start in range(1, 10 - length + 1):
num = 0
for i in range(length):
num = num * 10 + (start + i)
if low <= num <= high:
results.append(num)
return results
The inner loop that builds num is doing digit-by-digit construction. If start = 3 and length = 4, it computes:
num = 0 * 10 + 3 = 3num = 3 * 10 + 4 = 34num = 34 * 10 + 5 = 345num = 345 * 10 + 6 = 3456
That is 3456, a sequential digit number starting at 3 with length 4.
Visual walkthrough
Let's trace through the algorithm with low = 100 and high = 300. Since both are 3-digit numbers, only length-3 candidates can possibly fit (length-2 numbers are at most 89, and length-4 numbers start at 1234).
Step 1: Enumerate all sequential digit numbers (low=100, high=300)
There are only 36 possible sequential digit numbers total (lengths 2 through 9). We generate them all by iterating over each possible starting digit and length.
Step 2: Filter to range [100, 300]
100 ≤ num ≤ 300We only need length-3 numbers since low=100 has 3 digits and high=300 has 3 digits. From the length-3 candidates, only 123 and 234 fall within [100, 300].
Step 3: Return the result
The result is already sorted because we generate numbers in order of length and starting digit.
The algorithm generates all 36 candidates but only the ones in range make it into the result. Because we iterate in order, the output [123, 234] is already sorted.
Complexity analysis
| Metric | Value |
|---|---|
| Time | O(1), there are at most 36 sequential digit numbers to generate |
| Space | O(1), the output list contains at most 36 elements |
This is one of those rare problems where the complexity is truly constant. The total number of sequential digit numbers is fixed regardless of the input. You always do the same bounded amount of work. The range [low, high] only affects how many you keep, not how many you generate.
Building blocks
This problem is built from two techniques that you will reuse in other problems.
Enumeration by structure
Instead of searching through a huge space, you enumerate candidates based on the structural constraints of the answer. Sequential digit numbers are defined by just two parameters (start digit and length), so you loop over those parameters directly. This same idea works whenever the answer space is small but the search space is large.
Other problems that use this pattern:
- Palindrome Number (LeetCode 9) has structural constraints on digit symmetry.
- Count and Say (LeetCode 38) generates strings based on structural rules.
Digit-by-digit construction
Building a number one digit at a time using num = num * 10 + digit is a fundamental pattern. You will see it in string-to-integer conversion, reverse integer, and many math problems. The formula shifts existing digits left by one decimal place and appends the new digit.
num = 0
for digit in digits:
num = num * 10 + digit
Edge cases
low and high have the same number of digits. For example, low = 1000 and high = 9999. You only need to check length-4 candidates: 1234, 2345, 3456, 4567, 5678, 6789. The algorithm handles this naturally since other lengths will fall outside the range.
Only one valid number. If low = 120 and high = 130, the only sequential digit number in range is 123. The result is [123].
No valid numbers. If low = 300 and high = 400, no sequential digit number falls in that range (234 is below 300, and 345 is above 400... actually wait, 345 is above 400? No, 345 is between 300 and 400). Let's pick a better example: low = 400 and high = 450. 456 is above 450 and 345 is below 400, so the result is an empty list [].
Full range. If low = 10 and high = 123456789, you get all 36 sequential digit numbers.
From understanding to recall
Reading through this solution, the logic feels obvious. Sequential digits are determined by start and length, so you loop over both. But when you sit down to code it two weeks from now, the details can trip you up. Do you loop length from 2 to 9 or 2 to 10? Is the starting digit bound 9 - length or 9 - length + 1? Does num * 10 + (start + i) use start + i or start + i - 1?
Spaced repetition drills these details until they are automatic. CodeBricks breaks this problem into its building blocks: enumeration by structure and digit construction. You practice each piece separately, and after a few review cycles at increasing intervals, the loop bounds and the construction formula are second nature. When a variation appears in an interview, you are not re-deriving the solution. You are assembling bricks you already own.
Related posts
- Count and Say - Another problem where you generate values based on structural rules, using iterative construction
- Palindrome Number - A math problem that uses digit extraction and structural properties of numbers
- Happy Number - A math problem that uses digit manipulation and enumeration of a bounded sequence