【LeetCode-639】解码方法 2
问题
一条包含字母 A-Z 的消息通过以下的方式进行了编码:
'A' -> 1
'B' -> 2
...
'Z' -> 26
除了上述的条件以外,现在加密字符串可以包含字符'*'了,'*'可以被当做1到9当中的任意一个数字。
给定一条包含数字和字符'*'的加密信息,请确定解码方法的总数。
同时,由于结果值可能会相当的大,所以你应当对109 + 7取模。(翻译者标注:此处取模主要是为了防止溢出)
示例
输入:"*"
输出:9
解释:加密的信息可以被解密为: "A", "B", "C", "D", "E", "F", "G", "H", "I".
解答
class Solution {
public:
int numDecodings(string s) {
if (s.empty() || s[0] == '0') return 0;
long pre = 1, cur = 1; // 初始化dp[-1], dp[0]
if (s[0] == '*') cur = 9;
for (int i = 1; i < s.size(); i++) {
long tmp = cur;
if (s[i] == '*') {
if (s[i - 1] == '0') cur *= 9;
else if (s[i - 1] == '1') cur = 9 * (cur + pre);
else if (s[i - 1] == '2') cur = 9 * cur + 6 * pre;
else if (s[i - 1] == '*') cur = 9 * cur + 15 * pre;
else cur *= 9;
}
else if (s[i] == '0') { // 0,基本退化到解码方法I
if (s[i - 1] == '*') cur = 2 * pre;
else if (s[i - 1] == '1' || s[i - 1] == '2') cur = pre;
else return 0;
}
else { // 1~9
if (s[i - 1] == '*') {
if (s[i] < '7') cur += 2 * pre;
else cur += pre;
}
else if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] < '7')) cur += pre;
}
pre = tmp;
cur %= 1e9 + 7;
}
return cur;
}
};
重点思路
相较于“解码方法 1”,本题多了一个*号。这类动态规划只需要记录前两个值,所以并不需要初始化数组。本题难点在于各种边界条件,该解法的做法为,先判断当前值s[i],再判断上一个值s[i-1]。做这种题一定要有条理,不能想到啥加啥,否则很容易混乱。