Algorithm

Count and Say

Arrays & Strings Pattern

Count and Say

The count-and-say sequence is defined recursively: the first term is "1", and every later term is produced by reading the previous term aloud in digits — scanning it left to right and, for each run of identical adjacent digits, emitting the run's length followed by the digit itself. For example "1" reads as "one 1" → "11", which reads as "two 1s" → "21", which reads as "one 2, one 1" → "1211". Given an integer n, return the n-th term of the sequence as a string.

CONSTRAINTS
  • 1 <= n <= 30
  • Every term is a string of digits
EXAMPLE 1
Input: n = 1
Output: "1"
The seed term defined by the sequence itself.
EXAMPLE 2
Input: n = 4
Output: "1211"
Reading forward: "1" → "11" → "21" → "1211". The 4th term reads "21" as one 2 and one 1.
EXAMPLE 3
Input: n = 5
Output: "111221"
Reading "1211" gives one 1, one 2, then two 1s → "11" + "12" + "21" = "111221".
Does 'say' mean spelling out words, or writing digits?
Digits. A run of one 2 becomes the two characters "12", and three 1s become "31" — never the English words.
Can I compute term n directly without building the earlier terms?
No. Each term is defined purely as a reading of the term before it, so there is no closed form to jump to — you must generate terms 1 through n in sequence.
How large can n get, and does the string blow up?
n goes up to 30. Term lengths grow by roughly Conway's constant (≈ 1.303) per step, so the 30th term is a few thousand characters — large but easily handled.

The count-and-say sequence is built by reading the previous term out loud, in digits. Start from term 1, the string "1". To make the next term, scan the current one left to right and, for each run of the same digit repeated, write down how many there were followed by which digit it was: "1" is a single 1, read as "one 1", written "11". Then "11" is two 1s, "21". Then "21" is one 2 then one 1, "1211". Given n, we return the n-th term as a string.

The definition is honestly the whole problem — there is no hidden trick waiting to be uncovered. The skill being tested is reading a precise, self-referential rule and turning it faithfully into code. Two consequences of that definition matter before we write anything. First, the sequence is strictly sequential: term n is defined only in terms of term n-1, so there is no shortcut that jumps straight to term n — we must generate every term from 1 up to n in order. Second, every term is itself a string of digits, and it is those digits, never their numeric value, that the next term describes.

The one operation that does all the work: count the runs

Turning a term into the next one is a single, well-known operation called run-length encoding: replace each maximal run of identical symbols with the pair (count, symbol). To do it, walk the string with an index; at each new position start a run of length 1, then keep advancing while the next character equals the current one, tallying the length. When the run ends, emit the count as a digit followed by the digit itself, and continue from the character that broke the run.

python
result = "1"                         # term 1, the seed
for _ in range(n - 1):               # read it (n - 1) times to reach term n
    parts = []
    i = 0
    while i < len(result):
        digit = result[i]
        count = 1
        while i + 1 < len(result) and result[i + 1] == digit:
            count += 1
            i += 1                    # absorb the rest of this run
        parts.append(str(count) + digit)
        i += 1                        # step to the next run
    result = "".join(parts)
return result
Crucial Notebuild the next term in a list of pieces and join once at the end, rather than repeatedly doing result = result + piece inside the loop. In most languages a string is immutable, so + copies the entire accumulated string on every append — turning the construction of a length-L term into O(L²) work. Collecting pieces and joining once keeps each term's construction linear in its length. The same care applies to String Compression, which is run-length encoding under a different name.
Worked Example:n = 5
Build up term by term, each one read from the one above it:
- Term 1: "1" (the seed).
- Term 2: read "1" → one 1 → "11".
- Term 3: read "11" → two 1s → "21".
- Term 4: read "21" → one 2, then one 1 → "12" + "11" = "1211".
- Term 5: read "1211" → one 1, one 2, two 1s → "11" + "12" + "21" = "111221".
Answer for n = 5: "111221". Notice term 5's reading crosses a digit change ("2" then "11"): the trailing run of 1s has length 2, which is why it ends in "21" and not "11".
What it costs

Each reading pass is linear in the length of the current term, and the term lengths grow — famously by a factor approaching Conway's constant, ≈ 1.303 per step — so the n-th term has length on the order of 1.303ⁿ and dominates the total work. The whole computation is therefore linear in the size of its own output, which itself grows exponentially in n; there is no way around producing that output, since the answer is the n-th term. (A curiosity that falls out of the rules, worth stating in an interview: starting from "1", no digit ever appears four times in a row, so a run count is never more than 3 — the sequence describes itself too tightly to permit it.) The transferable lesson is small but real: when a problem says "describe the previous thing" or "encode repeats compactly", the tool is run-length encoding, and its implementation trap is always the same — accumulate pieces in a list, join once.

Interactive Strategy Visualization

count & say

Iterative Transcription
term (n-1): "1211"
1
2
1
1
generating term (n): building...
Waiting to transcribe groups...
🔍

Generating the 5th term from the 4th term: "1211".

O(1.303ⁿ) Run-Length Simulation · Output-Bounded