题目描述
![这里写图片描述](https://img-blog.csdn.net/20171002222647545?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRml0el8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这道题大致的意思就是给你一个全是数字的字符串,按照提供的编码存在几种把数字转化为字母的方式,题目大体上就是这个意思。从题目给出的例子可以看出,之所以存在翻译时的歧义(多种翻译结果),是因为对字符串的分割的不同,比如“123”可以分割为“1,2,3”,“12,3”“1,23”这三种情况。
可能目前还看不出什么,但是你可以试着写一写,比如“1”存在一种翻译方式,“12”存在两种翻译方式,“122”存在三种翻译方式,“1222”存在五种翻译方式。写到这,应该就可以看出Sn、Sn-1、Sn-2存在一种关系(Sn代表字符串的前n个字符)。
仔细一想就会发现,若字符串的最后一个字符能与倒数第二个字符的组合存在两种翻译结果,则Sn = Sn-1 + Sn-2。这个公式就和斐波那契一样了,不过不同的是这儿比斐波那契多了一个判断,只有满足时才符合这个公式。
可以结合原码看一下。什么样的条件下才能满足这个公式
class Solution {
public:
int numDecodings(string s) {
string::iterator i = s.begin();
int size = s.length();
if (size == 0) return 0;
int* result = new int[size];
if (s[0] == '0') {
return 0;
} else {
result[0] = 1;
}
if (s[0] > '2' && s[1] == '0') return 0;
if (((s[0] <= '2' && s[1] <= '6') || (s[0] >= '1' && s[0] < '2'))
&& s[0] != '0' && s[1] != '0')
result[1] = 2;
else
result[1] = 1;
int pre = 1;
for (int i = 2; i < size; ++i, ++pre) {
if (((s[pre] <= '2' && s[i] <= '6') || (s[pre] >= '1' && s[pre] < '2'))
&& s[pre] != '0' && s[i] != '0') {
result[i] = result[i - 1] + result[i - 2];
} else {
if (s[i] != '0')
result[i] = result[pre];
else
result[i] = result[pre - 1];
}
if ((s[pre] == '0' || s[pre] > '2') && s[i] == '0') return 0;
}
int ans = result[size - 1];
delete[] result;
return ans;
}
};