Decode Ways II

Decode Ways II

A.题意

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 109 + 7.

Example 1:
Input: “*”
Output: 9
Explanation: The encoded message can be decoded to the string: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.
Example 2:
Input: “1*”
Output: 9 + 9 = 18

这道题其实是另一道题目decode ways的升级版本吧,这里加多了星号表示1-9,然后要我们求出编码种类,题意大致如下

  • 1到26表示A-Z
  • 星号代表1-9任意数字
  • 输入一串带星号和数字的字符串按照上面两条规则编码返回可编码的种类

B.思路

对于这道题,我们发现编码的种类是随着字符串的增长改变的,我们用一个一维数组dp[i](这里dp[0]用于初始化了)来记录到s[i - 1]时可编码的数量,这样就分为以下三种情况

  • s[i - 1]为0
    这种情况下由于0只能与前面的1或2结合才能编码,所以根据情况,若s[i - 2]为1或2则dp[i] = dp[i - 2];
    若s[i - 2]为星号则星号表示1和2时满足编码条件则可知dp[i]为dp[i - 2]的两倍
    若不是上面两种情况则不可编码返回0

  • s[i - 1]为星号
    对于这种情况星号首先单独表示一个字符则有9种可能,首先我们给dp[i]加上9*dp[i - 1],
    接下来我们分析一下星号与前面的字符结合表示一个字符的编码个数,
    若前一个字符即s[i - 2]为1时,星号表示的9个数字均可以与1结合表示一种编码故可为dp[i]加上9 * dp[i - 2],
    若前一个字符即s[i - 2]为2时,星号只有表示1-6这6个数字时才能与2结合表示一种编码故为dp[i]加上6 * dp[i - 2],
    若前一个字符即s[i - 2]为号的时候则只有上述两种情况的全部能满足条件故为dp[i]加上15 dp[i - 2],

  • s[i - 1]为1到9其中一个字符
    这种情况下该字符可单独表示一个编码,所以先给dp[i]加上dp[i - 1],接下来同样地分析与前一个字符的结合情况,
    若s[i - 2]为1则任何s[i - 1]均能与其结合表示一种编码故再加上dp[i - 2],
    若s[i - 2]为2则只有s[i - 1]为1到6之间能满足编码条件,此时若s[i - 1]为1到6加上dp[i - 2]
    若s[i - 2]为星号,若s[i - 1]为1到6则星号表示1和2时能与其结合,此时加上2 * dp[i - 2],而若s[i - 1]为7到9则只有星号表示1能编码此时加上dp[i - 2]

C.代码实现

class Solution {
public:
    int numDecodings(string s) {
        int M = 1e9 + 7;
        vector<long> dp(s.size() + 1,0);
        dp[0] = 1;
        if (s[0] == '0')
        {
            return 0;
        }
        if (s[0] == '*')
        {
            dp[1] = 9;
        } else {
            dp[1] = 1;
        }
        for (int i = 2;i <= s.size();i++)
        {
            if (s[i - 1] == '0')
            {
                if (s[i - 2] == '1' || s[i - 2] == '2')
                {
                    dp[i] += dp[i - 2];
                } else if (s[i - 2] == '*') {
                    dp[i] += 2 * dp[i - 2];
                } else {
                    return 0;
                }
            }
            else if (s[i - 1] == '*')
            {
                dp[i] += 9 * dp[i - 1];
                if (s[i - 2] == '1')
                {
                    dp[i] += 9 * dp[i - 2];
                } else if (s[i - 2] == '2') {
                    dp[i] += 6 * dp[i - 2];
                } else if (s[i - 2] == '*') {
                    dp[i] += 15 * dp[i - 2];
                }
            }
            else if (s[i - 1] >= '1' && s[i - 1] <= '9') {
                dp[i] += dp[i - 1];
                if (s[i - 2] == '1')
                {
                    dp[i] += dp[i - 2];
                } else if (s[i - 2] == '2' && s[i - 1] <= '6') {
                    dp[i] += dp[i - 2];
                } else if (s[i - 2] == '*') {
                    dp[i] += (s[i - 1] >= '1' && s[i - 1] <= '6') ? (2 * dp[i - 2]) : dp[i - 2]; 
                }
            }
            dp[i] %= M;
        }
        return dp[s.size()];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值