A message containing letters from A-Z is being encoded to numbers using the following mapping way:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Beyond that, now the encoded string can also contain the character *, which can be treated as one of the numbers from 1 to 9.
Given the encoded message containing digits and the character *, return the total number of ways to decode it.
Also, since the answer may be very large, you should return the output mod 10^9 + 7.
Example
Example 1
Input: "*"
Output: 9
Explanation: You can change it to "A", "B", "C", "D", "E", "F", "G", "H", "I".
Example 2
Input: "1*"
Output: 18
Notice
- The length of the input string will fit in range [1, 10^5].
- The input string will only contain the character
*and digits0-9.
public class Solution {
/**
* @param s: a message being encoded
* @return: an integer
*/
public int numDecodings(String s) {
// write your code here
if (s == null || s.length() == 0) {
return 0;
}
if (s.charAt(0) == '0') {
return 0;
}
long MOD = (long)1e9 + 7;
int n = s.length();
long[] dp = new long[n + 1];
dp[0] = 1;
dp[1] = s.charAt(0) == '*' ? 9 : 1;
for (int i = 2; i <= n; i++) {
char c = s.charAt(i - 1);
// regular case
if (c != '*') {
if (c != '0') {
dp[i] = dp[i - 1];
}
int numCombinations = getNumberOfValidNumbers(s.charAt(i - 2), s.charAt(i - 1));
dp[i] += dp[i - 2] * numCombinations % MOD;
} else {
dp[i] = dp[i - 1] * 9 % MOD; // * match 1-9
int numCombinations = getNumberOfValidNumbers(s.charAt(i - 2), s.charAt(i - 1));
dp[i] += dp[i - 2] * numCombinations % MOD;
}
}
return (int)(dp[n] % MOD);
}
private int getNumberOfValidNumbers(char a, char b) {
// 4 cases:
// * *
// * num
// num *
// num num
int ans = 0;
if (a == '*' && b == '*') {
ans = 15; // 11 -> 26, not 10, 20
} else if (a == '*') {
int nb = Character.getNumericValue(b);
if (nb >= 0 && nb <= 6) {
ans = 2; // 1* and 21->26
} else {
ans = 1; // 1*
}
} else if (b == '*') {
int na = Character.getNumericValue(a);
if (na == 1) {
ans = 9; // 11-19
} else if (na == 2) {
ans = 6; // 21-26
} else {
ans = 0;
}
} else {
int na = Character.getNumericValue(a);
int nb = Character.getNumericValue(b);
int num = na * 10 + nb;
if (na == 0) {
ans = 0;
} else if (num >= 1 && num <= 26) {
ans = 1;
}
}
return ans;
}
}