~20 minutes · Day 70 · Decode Ways · Python
Tonight's problem is Decode Ways. Interviewers like it because it looks like plain counting, then quietly adds a rule: not every step is legal. A 0 cannot stand alone, 06 is not a letter, and only chunks from 1 to 26 count.
Climbing stairs with a bouncer: a one- or two-digit step only counts when the chunk it consumes is a valid letter code (1-26, no leading zero).
That is the whole trick. This is still a one-dimensional DP chain, but each move must pass a validity test before it is allowed to add ways.
The brute force is recursion: stand at index i, try consuming one digit, try consuming two digits, and count every path that reaches the end. Dynamic programming is built for this kind of repeated-subproblem counting (Wikipedia: dynamic programming).
def dfs(i):
if i == len(s): return 1
if s[i] == "0": return 0
ways = dfs(i + 1) # take one valid digit
if i + 1 < len(s) and 10 <= int(s[i:i+2]) <= 26:
ways += dfs(i + 2) # take two valid digits
return ways
This works, but it is O(2n) in the worst case: inputs like "111111" branch again and again into the same suffixes. The repeated question is: how many ways can the suffix starting at index i be decoded?
Let dp[i] mean: the number of ways to decode the suffix s[i:]. Python slices like s[i:i+2] read a short sequence chunk (Python docs: sequence operations). The answer lives at dp[0].
def num_decodings(s):
n = len(s)
dp = [0] * (n + 1)
dp[n] = 1 # empty suffix: one finished path
for i in range(n - 1, -1, -1):
if s[i] != "0": # one digit: 1..9 only
dp[i] += dp[i + 1]
if i + 1 < n and 10 <= int(s[i:i+2]) <= 26:
dp[i] += dp[i + 2] # two digits: 10..26 only
return dp[0]
Read the code as the four DP questions: state is dp[i], transition is valid one-step plus valid two-step, base is dp[n] = 1, answer is dp[0].
Before opening the reveal, predict the count for s = "11106". Say the two rules out loud: one digit must not be 0; two digits must be between 10 and 26.
The answer is 2: 1|1|10|6 and 11|10|6. The chunks 06 and lone 0 are rejected, so many stair-like paths never count.
| Approach | Time | Space |
|---|---|---|
| Brute force recursion | O(2n) | O(n) |
| DP table | O(n) | O(n) |
The DP table pays memory to stop re-solving the same suffix. Later, this can compress to O(1) space because each state only reads two future states, but the full table is clearer for the first pass.
1. What does dp[i] mean in this lesson?
dp[i] counts ways to decode the suffix starting at i. That makes the answer dp[0], the whole string.2. Which chunk is a valid two-digit letter code?
"10" is between 10 and 26. "06" has a leading zero, and "30" is too large.3. Spot the bug in this transition:
if s[i] != "0":
dp[i] += dp[i + 1]
if i + 1 < n and int(s[i:i+2]) <= 26:
dp[i] += dp[i + 2]
"06" because int("06") is 6. The lower bound 10 <= is what rejects leading-zero pairs.4. Which phrase best identifies this pattern?
Solve Decode Ways in your Notion tracker using the cycle — predict → attempt → compare → encode.
Watch NeetCode — Decode Ways after your attempt, as the compare step. Do not watch it before you have a written recurrence.
Stuck or curious? Ask your teacher (the agent) — that's what it's for.