Decode Ways
A digit string was produced by mapping 'A' to '1' through 'Z' to '26' and concatenating the codes with no separators between them. Count how many original letter messages could have produced the given digit string.
Do this lesson first: climbing stairsExample input
s = "123102618"
Expected output
12
Break it down
Answer each question out loud before you open it. Getting it wrong here is the useful part. A revealed answer you never guessed at teaches you nothing.
Fill the table
The table pauses before each cell you have to supply. Type the value the recurrence gives, and the write animation confirms it.
Press start. The animation stops at every cell YOUR recurrence must fill.
dp[0] = 1: an empty prefix has exactly one, vacuous, decoding. Every cell from i = 1 on depends only on dp[i - 1] and/or dp[i - 2], whichever readings are valid there, so filling left to right guarantees any dependency a cell needs already holds a real value before it is read.
- 1
function numDecodings(s) { - 2
const n = s.length; - 3
const dp = new Array(n + 1).fill(0); - 4
dp[0] = 1; - 5
for (let i = 1; i <= n; i++) { - 6
if (s[i - 1] !== '0') dp[i] += dp[i - 1]; - 7
if (i >= 2) { - 8
const two = Number(s.slice(i - 2, i)); - 9
if (two >= 10 && two <= 26) dp[i] += dp[i - 2]; - 10
} - 11
} - 12
return dp[n]; - 13
}
The code, the trap, the variations
- 1
function numDecodings(s) { - 2
const n = s.length; - 3
const dp = new Array(n + 1).fill(0); - 4
dp[0] = 1; - 5
for (let i = 1; i <= n; i++) { - 6
if (s[i - 1] !== '0') dp[i] += dp[i - 1]; - 7
if (i >= 2) { - 8
const two = Number(s.slice(i - 2, i)); - 9
if (two >= 10 && two <= 26) dp[i] += dp[i - 2]; - 10
} - 11
} - 12
return dp[n]; - 13
}
Where people go wrong
Treating a lone '0' as a normal digit that can stand on its own. No letter maps to '0', so wherever the digit itself is '0' (position 5 in this string), the single-digit reading is invalid and only the two-digit pair ending in that '0' can consume it. Skipping this check lets dp[5] wrongly add a phantom single-digit decoding of a digit with no letter at all.
Also allow '0' to map to a letter on its own.
The single-digit validity check no longer excludes '0', so a few cells that currently read only dp[i - 2] would start reading dp[i - 1] too. The two-digit check and the underlying two-term sum recurrence stay exactly the same.
Ask only whether at least one decoding exists, not how many.
combine would switch from summing the valid predecessors to an OR over whether either is nonzero. Which cells are read and when each reading is valid stay exactly the same.