call(back)
Algorithms & Data Structureshard

Reverse Count-and-Say

The count-and-say step reads a digit string run by run and writes count then digit for each run: "23" -> "1213" (one 2, one 3); "3" repeated 121 times -> "1213" as well; "11" -> "21"; "0" -> "10".

You are given a string s that is the output of exactly one such step. Return all original strings that produce s.

A valid parse of s

  • s splits left to right into pairs (count, digit): count is a positive integer with no leading zero (multi-digit counts like "121" are legal), digit is exactly one character 0-9.
  • Consecutive pairs must have different digits — equal digits would have been one longer run.
  • If s cannot be parsed, return []. s = "" returns [""], keeping the round trip consistent.
"1213"  => ["23", "3" x 121]     (12,1)(3…) leaves a lone digit — invalid
"11"    => ["1"]
"21"    => ["11"]
"10"    => ["0"]
"11112" => ["1" x 11 + "2", "1" + "2" x 11, "2" x 1111]
          (1,1)(1,1)(1,2) is rejected: two consecutive runs of "1"
"0", "01", "1", "a1"  =>  []

Return the originals sorted ascending. Originals can be exponentially long, so build them as (count, digit) runs and expand at the end — s stays short (<= 20) when materializing.

Part (b)

countOriginals(s): just the number of originals, for s up to length 2000.

Follow-ups

  • Why can one input be unambiguous while a near-identical one explodes?
  • Where exactly does the "adjacent digits differ" rule come from in the forward step?

Asked at