Problem Statement
Decode Ways
Imagine a secret code where each letter is a number. 'A' is 1, 'B' is 2, all the way up to 'Z' which is 26. Someone hands you a string of digits, like "12", and asks: how many different messages could this have started as? "12" could be "AB" (the 1 and the 2 read separately) or "L" (the 1 and 2 read together as 12). So there are 2 ways. Your job is to count all the valid ways to split the digit string back into letters. One catch: there is no letter for 0, so a 0 can never stand on its own.
Signals to notice
Brute force first
Recursively try decoding one or two digits at each position. Many substrings are re-decoded across different branches. It is a fair place to begin because it matches the surface of the question, yet it does not capture the deeper structure that makes the problem simpler.
The key insight
DP: dp[i] = (ways using single digit) + (ways using two digits). If s[i] is valid (1-9), add dp[i-1]. If s[i-1.i] forms 10-26, add dp[i-2]. Instead of recomputing the world every time, you preserve just enough context to let the next decision become obvious.
Trace it on s="226"
init: prev2=1, prev1=1 (s[0]='2' != '0')
i=1 s[1]='2': single ok +prev1=1; pair int('22')=22 in 10..26 +prev2=1 -> curr=2; shift prev2=1, prev1=2
i=2 s[2]='6': single ok +prev1=2; pair int('26')=26 in 10..26 +prev2=1 -> curr=3; shift prev2=2, prev1=3
loop ends, return prev1 = 3 ("2 26", "22 6", "2 2 6")What must stay true
At each position, you either decode one character or two. The total decodings is the sum of both valid choices. dp[i] depends only on dp[i-1] and dp[i-2]. When you keep that truth intact, each local choice supports the larger solution instead of fighting it.
Shape of the loop
prev2, prev1 = 1, (1 if s[0] != '0' else 0)
for i from 1 to len(s)-1:
curr = 0
if s[i] != '0': curr += prev1 # single digit
if 10 <= int(s[i-1:i+1]) <= 26: curr += prev2 # pair
prev2, prev1 = prev1, curr
return prev1Pseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Forgetting that '0' cannot be decoded alone — if s[i] = '0', there are zero ways from single-digit decoding. Also, leading zeros in two-digit codes (like '06') are invalid. The fix is usually to return to the meaning of each move, not just the steps themselves.