题目:
Amessage containing letters from A-Z is being encoded to numbers usingthe following mapping:
一条信息包含从A-Z的字母,但是这些字母使用下面的映射编码成了一串数字。
'A' -> 1
'B' -> 2
...
'Z' -> 26
Givenan encoded message containing digits, determine the total number of ways todecode it.
给定由数字组成的一串编码过的信息,确定这串数字可以有多少种解码方法。
Forexample,
Given encoded message "12", it could be decoded as "AB" (12) or "L" (12).
Thenumber of ways decoding "12" is 2.(12可能解码成AB,也可能解码成L,所以有2种解码方法)。
思路:
可以先参考爬楼梯问题:http://blog.csdn.net/u012243115/article/details/41089613。
但是这一题还要具体分析一些情况,因为从i-1到i+1以及从i到i+1是有条件的。
令dp[i+1]表示前i+1个字符(即s[0]到s[i])可以编码的数量
dp[i+1] = dp[i] + dp[i-1]
下面分析可以从i-1到i+1以及从i到i+1的条件
可以从i到i+1的条件:只要当前字符s[i] != ‘0’ ,即s[i] = "1,2,3,4,5,6,7,8,9",那么dp[i]就可以和当前字符组到一起,即"dp[i],s[i]"
可以从i-1到i+1的条件:前一个字符s[i-1]和当前字符s[i]要组在一起,即符合10<="s[i-1]s[i]" <= 26 即可,其他情况,s[i-1]s[i]都不能放在一起
代码1:
class Solution {
public:
int numDecodings(string s)
{
int n = s.size();
if( n<=0 || s[0]=='0')
return 0;
vector<int> dp(n+1, 0);
dp[1] = dp[0] = 1;
for(int i=2; i<=n; ++i)
{
if(s[i-1] != '0')
dp[i] = dp[i-1];
if(s[i-2]=='1' || (s[i-2]=='2'&&s[i-1]<'7'))
dp[i] += dp[i-2];
}
return dp[n];
}
};
代码2:
class Solution {
public:
//优化了空间复杂度,用几个动态变量保存当前i个字符的编码数量
int numDecodings(string s)
{
if(s.empty() || s[0] == '0')
return 0;
int pre_2 = 1;
int pre_1 = 1;
int cur = 0;
//注意遍历的当前字符是i-1,所以i可以取到s.size()
for(int i = 2 ; i <= s.size() ; i++)
{
if(s[i-1] != '0')
cur += pre_1;
if(s[i-2] == '1' || (s[i-2] == '2' && s[i-1] <'7'))
cur += pre_2;
pre_2 = pre_1;
pre_1 = cur;
cur = 0;
}
return pre_1;//循环结束时pre_1保存的才是解码数量,而cur为0
}
};