Leetcode 639. 解码方法 2【空间优化的动态规划】

问题描述

一条包含字母 A-Z 的消息通过以下的方式进行了编码:

‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
除了上述的条件以外,现在加密字符串可以包含字符 '‘了,字符’'可以被当做1到9当中的任意一个数字。

给定一条包含数字和字符’*'的加密信息,请确定解码方法的总数。

同时,由于结果值可能会相当的大,所以你应当对109 + 7取模。(翻译者标注:此处取模主要是为了防止溢出)

示例 1 :

输入: “*”
输出: 9
解释: 加密的信息可以被解密为: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.

解题报告

代码在 Leetcode 91. 解码方法 题解区:pris_bupt 的基础上修改的。

解决这个题目,关键在于抓住 当前数字单独解码的可能方案数+当前数字和前一个数字合在一起解码的方案数

所以需要分类讨论:

  • 当前数字为 0 时,要分上一个数字是 1 或者 2 或者 * 或者其他数字;
  • 当前数字为 * 时,要分上一个数字是 1 或者 2 或者 * 或者其他数字;
  • 当前数字在 [1,6] 的范围内时, 要分上一个数字是 1 或者 2 或者 * 或者其他数字;
  • 当前数字在 [7,9] 的范围内时, 要分上一个数字是 1 或者 2 或者 * 或者其他数字;
    具体实现如代码所示。

实现代码

class Solution{
    public:
        int numDecodings(string s) {
            if(s[0]=='0') return 0;
            long long pre = 1, curr = (s[0]=='*')?9:1;//dp[-1] = dp[0] = 1
            int MOD = 1e9 + 7;
            for (int i = 1; i < s.size(); i++) {
                int tmp = curr;
                if (s[i] == '0')
                    if (s[i - 1] == '1' || s[i - 1] == '2') curr = pre;
                    else if(s[i-1]=='*') curr=pre*2;
                    else return 0;
                else if(s[i]=='*'){
                    if(s[i-1]=='1') curr=(pre+curr)*9;
                    else if(s[i-1]=='2') curr=pre*6+curr*9;
                    else if(s[i-1]=='*') curr=curr*9+pre*15;
                    else curr=curr*9;
                }
                else if(s[i]>='1'&&s[i]<='6'){
                    if(s[i-1]=='1'||s[i-1]=='2') curr = curr + pre;
                    else if(s[i-1]=='*') curr=2*pre+curr;
                }
                else if(s[i]>='7'){
                    if(s[i-1]=='1'||s[i-1]=='*') curr = curr + pre;
                }
                pre = tmp;
                curr=curr%MOD;
            }
            return curr;
        }
};

参考资料

[1] Leetcode 639. 解码方法 2
[2] Leetcode 91. 解码方法 题解区:pris_bupt

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/106660530