A message containing letters from A-Z
is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
算法思想:对于一个message中的某个数字,考察其后面的数字,有以下几种截断情况:
1,若数字大于2,只有一种解码方式,即该数字不可能跟后面数字联合;
2,若数字小于等于2,其后面的数字等于0,也只有一种解码方式,这两个数字必须联合解码;
3,若数字等于1,其后面的数字大于2,有两种解码方式;
4,若数字等于2,其后面的数字大于2且小于等于6,有两种解码方式;
5,若数字等于2,其后面的数字大于6,有一种解码方式;
6,若数字小于等于2,其后面的数字小于等于2且不等于0,那么继续考察接下来的数字,直到出现上面的截断情况为止,
例如“212122212123”,其联合解码长度为12,最后的“3”可以单独解码也可与前面的“23”一起解码;
“212122212120”,其联合解码长度为11,最后的“20”必须一起解码;
“212122212127”;其联合解码长度为11,最后的“7”必须单独解码;
假设截断序列中的联合解码长度为n,其解码的方式有T(n)种,
那么有递推公式,T(n)=T(n-1)+T(n-2),这是一个斐波那契数列,利用迭代法求,参见下面的代码;
将一个message按照 上面的情况截断成各个解码段,算出每段的解码数,相乘即可。
int numDecodings(string s)
{
vector
FS;
int len;
int num;
if (s == "") return 0;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '0')
return 0;
if (s[i] < '3')
{
len = 1;
while (++i < s.length())
{
if (s[i-1] == '2' && s[i] > '6') break;
else if (s[i] == '0')
{
len--;
break;
}
else if (s[i] > '2')
{
len++;
break;
}
else
{
len++;
}
}
FS.push_back(len);
}
}
num = 1;
for (int i = 0; i < FS.size(); i++)
{
int temp1 = 0;
int temp2 = 1;
int temp3 = 1;
for(int j = 0; j < FS[i]; j++)
{
temp3 = temp1 + temp2;
temp1 = temp2;
temp2 = temp3;
}
num = num * temp3;
}
return num;
}