639. Decode Ways II

问题描述:

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

 

Note:

  1. The length of the input string will fit in range [1, 105].
  2. The input string will only contain the character '*' and digits '0' - '9'.

 

解题思路:

首先,单个数字和两个数字都有可能有对应的字母,单个数字为1-9,两个数字为10-26.

所以假设我们要求前n个数字的可能的结果:那么只与n-1和n-1个数字的可能性有关。(用prev1,prev2来表示)

这里有一个特殊情况:0。

  1. 当0出现首位的时候,没有对应的排列,返回0

  2. 当0出现在中间的时候(即s[n] == '0'),只有在s[n-1]为‘1’,‘2’, ‘*’时有效。

对于其他情况,即不为0的情况:

又分为两种情况:(cur 代表 当前可能的解码个数)

  1.为数字: 1-9:一个数字只能有一个对应的字母 cur = 1

  2.为‘*’:有9个对应的字母 cur = 9

需要对前一个数字进行分类讨论:

1.  s[n-1] == '0' :此时只与prev2和s[n]有关: cur = cur * prev2

2. s[n-1] == '1': 此时若后面为任意数字,都可以与1构成一个有效的解码方式; 若为*:则有9种

         cur = prev1 * cur + prev2 * cur; 

3. s[n-1] == '2' 此时后面只有在 < '7'的情况下能构成有效解码 

         cur = prev1 * (cur == 9 ? 6 : (s[i] > '6' ? 0 : 1)) + prev2 * cur;

4. s[n-1] == '*' *可以代替前面1-9的数字,所以对任意数字‘*’ 作为‘1’时一定成立,‘*’作为‘2’时有限制

          cur = prev1 * (cur == 9 ? 15 : (s[i] > '6' ? 1 : 2)) + prev2 * cur;

记得更新prev1,prev2

需要注意的是:

对每一次的结果(即)prev2都要取模,否则有溢出的危险

代码:

class Solution {
public:
    int numDecodings(string s) {
        long long prev1 = 1;
        long long prev2 = 1;
        long long m = 1e9 + 7;
        if(!s.empty() && s[0] == '0') return 0;
        for(int i = 0; i < s.size(); i++){
            long long cur = s[i] == '*' ? 9 : 1;
            if(i > 0){
                if(s[i] == '0'){
                    if(s[i-1] == '0' || s[i-1] > '2') return 0;
                    int temp = prev1;
                    prev1 = prev2;
                    prev2 = s[i-1] == '*' ? temp*2 : temp;
                    continue;
                }
                if(s[i-1] == '0'){
                    cur = prev2*cur;
                }else if(s[i-1] == '1'){
                    cur = prev1 * cur + prev2 * cur; 
                }else if(s[i-1] == '2'){
                    cur = prev1 * (cur == 9 ? 6 : (s[i] > '6' ? 0 : 1)) + prev2 * cur;
                }else if(s[i-1] == '*'){
                    cur = prev1 * (cur == 9 ? 15 : (s[i] > '6' ? 1 : 2)) + prev2 * cur;
                }else{
                    cur *= prev2;
                }
            }
            prev1 = prev2;
            prev2 = cur % m;
        }
        
        return (int)prev2;
    }
};

 

posted @ 2018-07-13 10:50  妖域大都督  阅读(116)  评论(0编辑  收藏  举报