这道题想到了用dp做,其实最后还是在缝缝补补,不过现在思路清晰一点了,这道题的难点就是0的decode
思路:首先要想明白的是,开头是0或者有连续两个0,那么decode就会失败,即return 0,想明白这点剩下的就简单了,想到用dp做的原因是,我们把假设string 是121,想象成一个一个放入,一开始容器只有一个1,之后再放入2,那么ways的增加即是新放入的2与原来的way decode中单独存在的1成功构成编码的个数,在我们的假设中,能成功构成的编码有一个,即12
还是不懂?再详细举例一个 假设string 为2260
一开始容器为一个2 (1)
之后放入2,原来单独存在的2有一个,且22能够decode,所以22的ways为2(1+1)
再放入6,原来的decode way为两条:2|2 ;22
可以看到,单独存在的前一个只有一个(2|2)且6与2(26)能够decode,所以226的ways为(2+1)
再放入0,原来的decode way为3条:22|6;2|2|6;2|26
可以看到,单独存在的前一个有两个(22|6)和(2|2|6),但是0与6(60)不能够decode,所以增加的为0,但是0又不能单独存在,所以deocode失败(前面那些2啊6啊都能单独存在,所以他们可以把前面的dp结果当成基数)
代码挺乱的,我也挺懒的,仔细看应该看得懂吧,毕竟我感觉我已经把我能想到的都讲了。。
class Solution {
public:
int dp[10000];
int numDecodings(string s) {
if (s[0] == '0')return 0;
dp[0] = 1;
int n = s.length() - 1;
for (int i = 1; i <= n; ++i) {
if ((s[i - 1] == '2'&&s[i] > '6')||(s[i-1]>'2'&&s[i]!='0'))dp[i] = dp[i - 1];
else if (s[i] == '0') {
if (s[i - 1] > '2'||s[i-1]=='0')return 0;
int dc = i == 1 ? dp[i - 1] : dp[i - 2];
dp[i] = dc;
}
else {
if(s[i-1]=='0')dp[i]=dp[i-1];
else {
int ic = i == 1 ? 1 : dp[i - 2];//increase
dp[i] = dp[i - 1] + ic;
}
}
}
return dp[n];
}
};