Decode Ways II - LeetCode

Decode Ways II - LeetCode

题目
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 1:
Input: “*”
Output: 9
Explanation: The encoded message can be decoded to the string: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.


特地找了一道动态规划的题目做,这道题还是比较简单的。
给出一串以'0-9','*'组成的字符串,算出这串字符所能代表的message的个数。

想法是用一个数组a[i]表示前i个字符所能表示的最大的message个数。然后a[i+1]就是在i个字符的基础上加一个字符,新加的字符可以单独解析,也可以和前一个合并,有两种情况。

接下来分类讨论就可以。

class Solution {
public:
    int numDecodings(string s) {
        if (s[0] == '0') return 0;
        long m[100005] = {0};
        m[0] = 1;
        if (s[0] == '*') m[1] = 9;
        else m[1] = 1;
        for (int i = 1; i < s.length(); i++) {
            if (s[i-1] == '1') {
                if (s[i] != '*' && s[i] != '0') m[i+1] = m[i]+m[i-1];
                else if (s[i] == '0') m[i+1] = m[i-1];
                else if (s[i] == '*') m[i+1] = 9*m[i]+9*m[i-1];
            } else if (s[i-1] == '2') {
                if (s[i]-'0' <= 6 && s[i]-'0' >= 1) m[i+1] = m[i]+m[i-1];
                else if (s[i] == '0') m[i+1] = m[i-1];
                else if (s[i] == '*') m[i+1] = 9*m[i]+6*m[i-1];
                else m[i+1] = m[i];
            } else if (s[i-1] == '*') {
                if (s[i] == '0') m[i+1] = 2*m[i-1];
                else if (s[i] == '*') m[i+1] = 9*m[i]+15*m[i-1];
                else if (s[i]-'0' <= 6 && s[i]-'0' >= 1) m[i+1] = m[i]+2*m[i-1];
                else m[i+1] = m[i]+m[i-1];
            } else {
                if (s[i] == '*') m[i+1] = 9*m[i];
                else if (s[i] == '0') return 0;
                else m[i+1] = m[i];
            }
            if (m[i+1] > 1000000007) m[i+1] %= 1000000007;
        }
        // for (int i = 0; i < s.length(); i++) {
        //     cout << m[i] << endl;
        // }
        return m[s.length()];
    }
};

别人的代码

class Solution {
public:
    int numDecodings(string s) {
        if (s.empty())
            return 0;
        long first = 1, second = 0;
        if (s[0] == '*')
            second = 9;
        else if (s[0] > '0' && s[0] <= '9')
            second = 1;

        for (int i = 1; i < s.size();i++) {
            long temp = 0;
            if (s[i] == '*') {
                temp = second*9;
                if (s[i-1] == '*')
                    temp += first*15;
                else if (s[i-1] == '1')
                    temp += first*9;
                else if (s[i-1] == '2')
                    temp += first*6;
            }
            else {
                temp = s[i] == '0'?0:second;
                if (s[i-1] == '*') {
                    if (s[i] >= '0' && s[i] <= '6')
                        temp += 2*first;
                    else 
                        temp += first;
                }
                else if ((s[i-1] == '1')||(s[i-1] == '2' && s[i] >= '0' && s[i] <= '6'))
                    temp+=first;
            }
            first = second;
            second = temp%1000000007;
        }
        return second;
    }
};

这个方法的想法的基础也是动态规划,不过做了一些优化。
因为a[i]的值只可能由a[i-1],a[i-2]导出,所以只需要保存这两个值(也就是代码中的first,second)就可以。
另外他的分类方法也比我的简单,再一次感觉自己蠢爆。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值