1. Problem statement
You’ve intercepted a secret message encoded as a string of digits. Your task is to determine how many different ways this string can be decoded into letters, based on the following mapping:
"1" → 'A' "2" → 'B' ... "26" → 'Z'
Rules:
- A single digit (like
"1") or a pair of digits (like"12") can be decoded if it falls within the range"1"to"26". - A leading zero (like
"06") is not valid and cannot be decoded. - You must decode the entire string, and you can only decode contiguous digits from left to right.
- Return the total number of valid ways to decode the string.
- If no valid decoding is possible, return
0.
Example 1:
Input: "12" Output: 2 Explanation: "12" can be decoded as "AB" (1 2) or "L" (12)
Example 2:
Input: "226" Output: 3 Explanation: "226" can be decoded as: - "BZ" (2 26) - "VF" (22 6) - "BBF" (2 2 6)
2. How the Solution Works
Imagine you’re walking along the string from left to right. At every position, you’re asking:
“How many ways can I decode everything up to this point?”
You use a list (we call it dp[]) where:
dp[i] tells you how many ways you can decode the first i characters of the string.
At each step:
You look at:
- The last 1 digit → is it valid? (i.e., not
"0") - The last 2 digits → is it a number between
"10"and"26"?
If it’s valid, you add the number of ways from the earlier position.
3. Visual Representation Example: "226"
We create an array dp[] like this:
s = "2 2 6"
↑ ↑ ↑
i = 1 2 3
dp[0] = 1 // Base case: empty string → 1 way
dp[1] = 1 // '2' is valid → 1 way
dp[2] = 2 // '2' and '22' are valid → 2 ways: [2,2] and [22]
dp[3] = 3 // '6' is valid, '26' is also valid → 3 ways total
3.1 How the decoding works
"226" can be split as: 1. [2, 2, 6] → B B F 2. [22, 6] → V F 3. [2, 26] → B Z → Total: 3 ways
4. Java implementation
public class DecodeWays {
public int numDecodings(String s) {
if (s == null || s.length() == 0) return 0;
int n = s.length();
int[] dp = new int[n + 1]; // dp[i] represents #ways to decode s[0..i-1]
dp[0] = 1; // base case: empty string
// base case: one character
dp[1] = s.charAt(0) != '0' ? 1 : 0;
for (int i = 2; i <= n; i++) {
char oneDigitChar = s.charAt(i - 1);
char twoDigitFirstChar = s.charAt(i - 2);
// Check single digit
if (oneDigitChar != '0') {
dp[i] += dp[i - 1];
}
// Check two-digit number from s[i-2] and s[i-1]
int twoDigit = Integer.parseInt(s.substring(i - 2, i));
if (twoDigit >= 10 && twoDigit <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
}
