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]的兩倍
若不是上面兩種情況則不可編碼返回0s[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()];
}
};