- 解码方法 II
动态规划, 以 i 为结尾的数目 由 i - 1 和i - 2 推到过来,也就是当前单个字符为一种分法,当前和前一个字符为一个分法。
以单个字符为一种分发那么
d
p
[
i
]
=
d
p
[
i
−
1
]
∗
x
dp[i] = dp[i - 1]*x
dp[i]=dp[i−1]∗x其中x 为当前的情况数 ,如果当前字符为 * 那么 情况数为 9 如果当前字符为 ‘0’ 则情况数为0,其他情况则为 1
与前面一个字符一起作为一个分发则
d
p
[
i
]
=
d
p
[
i
−
2
]
∗
y
dp[i] = dp[i - 2]*y
dp[i]=dp[i−2]∗y分别判断 ‘**‘, ’*?‘,’?*‘ ,’??’, 这四种情况, ?表示数字,
其中第一种 有 11 - 26 15中情况, 第二种 如果当前字符 小于 2 则有 2中情况, 第3种 如果前一个字符为0,有0种, 为1, 有9种, 为2,有6种, 最后一种要判断一下前面一位 是否 为 1 或者2 否则都是0
所以总的来说 d p [ i ] = d p [ i − 1 ] ∗ x + d p [ i − 2 ] ∗ y dp[i] = dp[i - 1]*x + dp[i -2]*y dp[i]=dp[i−1]∗x+dp[i−2]∗y 因为只与前面两个字符有关系所以用两个变量代替一下就不需要开一个新的数组了, 分别求一下 x和y就可以得到当前的情况数了
class Solution {
public:
long long mod = 1000000007;
long long cal_x(char a, char b){
if (b == '*' && a == '*'){
return 15;
}
else if (b != '*' && a == '*'){
if (b <= '6')
return 2;
else return 1;
}
else if(b == '*' && a == '2'){
return 6;
}
else if(b == '*' && a == '1'){
return 9;
}
else if(b != '*' && a != '*'){
if (a == '1' || a == '2' && b <='6'){
return 1;
}
return 0;
}
return 0;
}
long long cal_y(char a){ //最后一位
if (a == '*'){
return 9;
}
else if(a == '0'){
return 0;
}
else {
return 1;
}
return 0;
}
int numDecodings(string s) {
long long a = 1, b = 1 , c = 0;
for(int i = 0; i < s.size(); i ++){
c = 1LL*cal_y(s[i])*b %mod;
if (i >= 1){
c = (c + 1LL*cal_x(s[i - 1], s[i])*a%mod)%mod;
}
a = b;
b = c;
}
return c;
}
};