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.
初步思路:从前往后解码,遇到分支,就递归。 出现问题,子问题重复求解。
进一步,于是想到动态规划,把子问题记录下来,那么得先解子问题,于是想到从后往前解。
觉得和跳台阶斐波那契问题很像,但是是有约束条件的,
从后往前的 n 长序列 的解码方式数 f(n)=0 f(n) += f(n-1) 当 s[n] != '0' 从后往前的 第n个字符
f(n) += f(n-2) 当s[n,n-1] 构成 “10"--"26"; 从后往前的 第n,n-1个字符
那么可以用迭代法,用 a,b,c三个变量就可以了 。
给出两个解法:
class Solution {
public:
int help(string &s,int a,int b)
{
int len = b - a +1;
if(len <= 1)
return 1;
for(int i = a ; i <= b ; i++)
{
if(s[i]=='0')
return 0;
if( s[i]=='2' && i + 1 <= b && s[i+1] <= '6' )
{
return help(s,i+1,b)+help(s,i+2,b);
}
if( s[i]=='1' && i + 1 <= b )
{
return help(s,i+1,b)+help(s,i+2,b);
}
}
return 1;
}
int numDecodings(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int len = s.size();
if(len ==0)
return 0;
return help(s,0,len-1);
}
};
进一步的代码,ps. f(0)==1 这个感觉很诡异,但是 当 最后两个字符能构成 10-26时, 就构成了一种解,那么添加f(2) += f(0) 应该为1;
或者让代码自然一点,把 f(1) 和 f(2) 先分别求出来, 对大于3的情况 再做for 循环。
class Solution {
public:
int numDecodings(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int len = s.size();
if(len ==0)
return 0;
int a = 1;//f(n-2)
int b = 0;//f(n-1)
// f(n) += f(n-1) s[n] != '0';
// f(n) += f(n-2) s[n,n-1] eq "10"-"26";
if(s[len-1]!='0')
b = 1;
if(len==1)
return b;
int c ;
for(int i = 2; i <=len; i++)
{
string tmp = s[len-i]+s[len-i+1];
c = 0;
if(s[len-i]!='0')
c += b;
if(s[len-i]=='1' || s[len-i]=='2' && s[len-i+1] <= '6')
c += a;
a = b;
b = c;
}
return c;
}
};