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.
开始自然想到递归解决,并且开始时理解题意有误,类似01、001这种情况不等于1,不能解码,10是正确可以解码的。
代码如下:
class Solution {
public:
int numDecodings(string s) {
if(s.empty())
return 0;
int result=0;
getResult(&result, s, 0);
return result;
}
void getResult(int* result, string& s, int k)
{
if(k == s.length())
{
(*result)++;
return;
}
if(s[k] != '0')
getResult(result, s,k+1);
else//0为一位数字或两位数字的第一位时,直接返回,没有结果
return;
if(k<s.length()-1)
{
if(s[k]=='1' || (s[k]=='2' && s[k+1]<='6'))
getResult(result, s, k+2);
}
}
};
此解法随字符串的长度增长,时间复杂度成指数增长,不出意料,超时了。
正确的解法是动态规划,和“斐波那契”爬楼梯很像,只不过“一位数字”和“两位数字”都不能是以0开头。
代码如下:
class Solution {
public:
int numDecodings(string s) {
if(s.empty())
return 0;
int len = s.length();
int* F = new int[len+1];
for(int i=0; i<=len; ++i)
F[i] = 0;
if(s[0] == '0')
return 0;
if(s[0] == '1' || (s[0] == '2' && s[1] <= '6'))
F[0] = 1;
if(s[1] != '0')
F[1] = 1;
for(int i=2; i<=len; ++i)
{
if(s[i-1] != '0')
F[i] += F[i-1];
if(s[i-2] == '1' || (s[i-2] == '2' && s[i-1] <= '6'))
F[i] += F[i-2];
}
return F[len];
}
};