【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]。做这种题一定要有条理,不能想到啥加啥,否则很容易混乱。

posted @ 2020-12-29 08:54  tmpUser  阅读(96)  评论(0编辑  收藏  举报