問題描述
一條包含字母 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