Back to Python Examples

Decode Ways

A tricky DP problem where the base cases are the hardest part — zeros break everything.

Contents

  1. The Problem
  2. The DP Insight
  3. The Solution
  4. Trace — "226"
  5. Handling Zeros

1. The Problem

A message is encoded as a number string where A=1, B=2, ..., Z=26. Given an encoded string, return the number of ways to decode it.

# "12" → 2 ways:  "AB" (1,2)  or  "L" (12)
# "226"→ 3 ways:  "BZ" (2,26), "VF" (22,6), "BBF" (2,2,6)
# "06" → 0 ways:  no letter maps to 0 or 06

2. The DP Insight

At each position i, there are two choices:

dp[i] = total valid decodings of the first i characters.

3. The Solution

def num_decodings(s):
    if not s or s[0] == '0':
        return 0

    n = len(s)
    dp = [0] * (n + 1)
    dp[0] = 1  # empty string: 1 way to decode
    dp[1] = 1  # first char: 1 way (we checked it's not '0')

    for i in range(2, n + 1):
        one_digit = int(s[i - 1])
        two_digit = int(s[i - 2:i])

        if 1 <= one_digit <= 9:
            dp[i] += dp[i - 1]
        if 10 <= two_digit <= 26:
            dp[i] += dp[i - 2]

    return dp[n]

print(num_decodings("12"))   # 2
print(num_decodings("226"))  # 3
print(num_decodings("06"))   # 0

4. Trace — "226"

ione_digittwo_digitdp[i]Reasoning
01Base: empty string
11Base: "2" has 1 decoding
22 (valid 1–9)22 (valid 10–26)2dp[1] + dp[0] = 1+1
36 (valid 1–9)26 (valid 10–26)3dp[2] + dp[1] = 2+1

Answer: dp[3] = 3

5. Handling Zeros

print(num_decodings("10"))   # 1  ("J"=10, can't decode as 1+0)
print(num_decodings("100"))  # 0  (no way to decode — "100" has no valid split)
print(num_decodings("2101")) # 1  ("U"+"A" = 21,0,1 — only 10+1="JA" → but 21=U, 01 invalid)
Zeros are the hardest part. A '0' cannot be decoded as a single digit (there is no letter 0). It can only appear as the second digit of 10 or 20. Any other position produces 0 valid decodings. The bounds check 10 ≤ two_digit ≤ 26 handles this correctly.
This problem has the same structure as Climbing Stairs — dp[i] depends on dp[i-1] and dp[i-2] — but with conditional additions based on validity. You can space-optimize to O(1) using two rolling variables exactly like Climbing Stairs.