Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions problems/1291-sequential-digits/analysis_daily_20260713.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 1291. Sequential Digits

[LeetCode Link](https://leetcode.com/problems/sequential-digits/)

Difficulty: Medium
Topics: Enumeration
Acceptance Rate: 66.0%

## Hints

### Hint 1

Before reaching for a data structure, ask a smaller question: *how many* integers with sequential digits even exist? A number that starts at some digit and increases by one each step is completely determined by two things — where it starts and how long it is. That severely limits the possibilities. Think about counting the whole universe of valid numbers rather than scanning every number in `[low, high]`.

### Hint 2

The range can be as large as `10^9`, so iterating from `low` to `high` and checking each number is far too slow. Instead, *generate* only the numbers that qualify. Every sequential-digit number is a contiguous substring of a single fixed string. What is that string, and how can you slide a window across it?

### Hint 3

The key insight: every sequential-digit number is a substring of `"123456789"`. There are only 36 such substrings of length ≥ 2. Slide a window of each possible length (2 through 9) across `"123456789"`, convert each window into an integer, and keep the ones that fall inside `[low, high]`. If you enumerate by increasing length, and within each length from left to right, the results come out already sorted.

## Approach

The whole problem hinges on one observation: a number has sequential digits exactly when its digit string is a contiguous slice of `"123456789"`. For example `345` is the slice `"345"`, and `6789` is the slice `"6789"`. No sequential-digit number can contain a `0` (there is nothing before `1`), and none can wrap past `9`, so this single string captures every possibility.

That means the entire universe of sequential-digit numbers is tiny and fixed, independent of the input:

- Length 2: `12, 23, 34, 45, 56, 67, 78, 89`
- Length 3: `123, 234, ..., 789`
- ...
- Length 9: `123456789`

The algorithm:

1. Let `digits = "123456789"`.
2. For each window `length` from `2` to `9`:
- For each starting index `start` such that the window `[start, start+length)` fits inside the string:
- Build the integer by folding the window's characters: `num = num*10 + (digits[i] - '0')`.
- If `low <= num <= high`, append it to the result.
3. Return the result.

Because we iterate length ascending (shorter numbers are always numerically smaller) and, within a length, left-to-right (larger starting digit means a larger number), the output is naturally in sorted order. A defensive `sort.Ints` is included but is not strictly required.

**Walkthrough for `low = 100, high = 300`:** Length-2 windows produce `12..89`, all below `100`, so none qualify. Length-3 windows produce `123, 234, 345, ...`; `123` and `234` are in `[100, 300]`, but `345` and beyond exceed `300`. Length-4+ numbers are all `≥ 1234 > 300`. Result: `[123, 234]`. ✅

## Complexity Analysis

Time Complexity: O(1) — the number of candidate substrings of `"123456789"` is a fixed constant (36 numbers of length ≥ 2), independent of `low` and `high`. Building each number costs at most 9 steps. The optional sort is over ≤ 36 elements, also constant.

Space Complexity: O(1) — aside from the output list, only a few scalar variables are used. The output itself holds at most 36 integers.

## Edge Cases

- **No numbers in range** (e.g. `low = 140, high = 150`): No sequential-digit number lands in this window, so the answer is an empty list. The generate-and-filter approach handles this naturally by simply appending nothing.
- **Single valid number** (e.g. `low = 123, high = 123`): The range collapses to one value; the inclusive bounds `low <= num <= high` must both be non-strict so the endpoint is captured.
- **Boundary around a length change** (e.g. `low = 58, high = 155`): The valid numbers straddle two-digit and three-digit results (`67, 78, 89, 123`), confirming that mixing lengths still yields correctly sorted output.
- **Upper limit `10^9`**: The largest sequential-digit number is `123456789` (9 digits), which is less than `10^9` (10 digits). So a range like `low = high = 10^9` yields an empty list — make sure the loop never tries a length beyond 9.
43 changes: 43 additions & 0 deletions problems/1291-sequential-digits/problem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
number: "1291"
frontend_id: "1291"
title: "Sequential Digits"
slug: "sequential-digits"
difficulty: "Medium"
topics:
- "Enumeration"
acceptance_rate: 6597.4
is_premium: false
created_at: "2026-07-13T04:07:57.382751+00:00"
fetched_at: "2026-07-13T04:07:57.382751+00:00"
link: "https://leetcode.com/problems/sequential-digits/"
date: "2026-07-13"
---

# 1291. Sequential Digits

An integer has _sequential digits_ if and only if each digit in the number is one more than the previous digit.

Return a **sorted** list of all the integers in the range `[low, high]` inclusive that have sequential digits.



**Example 1:**


**Input:** low = 100, high = 300
**Output:** [123,234]


**Example 2:**


**Input:** low = 1000, high = 13000
**Output:** [1234,2345,3456,4567,5678,6789,12345]




**Constraints:**

* `10 <= low <= high <= 10^9`
31 changes: 31 additions & 0 deletions problems/1291-sequential-digits/solution_daily_20260713.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import "sort"

// Sequential Digits (LeetCode 1291)
//
// Every number with sequential digits is a contiguous substring of the fixed
// string "123456789". We slide a window of each possible length (2..9) across
// that string, turn each window into an integer, and keep the ones that fall
// inside [low, high]. This enumerates the entire (tiny, constant-size) universe
// of candidates instead of scanning the potentially huge [low, high] range.
func sequentialDigits(low int, high int) []int {
const digits = "123456789"

result := []int{}
for length := 2; length <= len(digits); length++ {
for start := 0; start+length <= len(digits); start++ {
num := 0
for i := start; i < start+length; i++ {
num = num*10 + int(digits[i]-'0')
}
if num >= low && num <= high {
result = append(result, num)
}
}
}

// The generation order already yields sorted output, but sort defensively.
sort.Ints(result)
return result
}
61 changes: 61 additions & 0 deletions problems/1291-sequential-digits/solution_daily_20260713_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package main

import (
"reflect"
"testing"
)

func TestSolution(t *testing.T) {
tests := []struct {
name string
low int
high int
expected []int
}{
{
name: "example 1: range 100 to 300",
low: 100,
high: 300,
expected: []int{123, 234},
},
{
name: "example 2: range 1000 to 13000",
low: 1000,
high: 13000,
expected: []int{1234, 2345, 3456, 4567, 5678, 6789, 12345},
},
{
name: "edge case: no sequential digits in range",
low: 140,
high: 150,
expected: []int{},
},
{
name: "edge case: single value range with one match",
low: 123,
high: 123,
expected: []int{123},
},
{
name: "edge case: boundary spanning two- and three-digit numbers",
low: 58,
high: 155,
expected: []int{67, 78, 89, 123},
},
{
name: "edge case: upper limit 10^9 has no 10-digit sequential number",
low: 1000000000,
high: 1000000000,
expected: []int{},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := sequentialDigits(tt.low, tt.high)
if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("sequentialDigits(%d, %d) = %v, want %v", tt.low, tt.high, result, tt.expected)
}
})
}
}