Description:
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.
分析:这道题看似很简单,上手写起来发现错误百出,心累,所以说这样的多情况的问题一定要先在纸上分析出所有的情况再code,不然想一出情况写一出肯定会出问题。好了,接下来分析这道题。首先这道题是一道动态规划问题,然后动态规划问题先要找到递推公式,然后写出相应代码。对于动态规划问题过几天再写一篇总结。
分为以下四种情况(具体条件看代码即可)
代码如下:
class Solution {
public:
int numDecodings(string s)
{
if(s[0] == '0' || s.empty())
return 0;
vector<int> ret(s.size() + 1, 0);
ret[1] = ret[0] = 1;
for(int i = 1; i < s.size(); i++)
{
if(s[i] == '0')
{
if(s[i - 1] != '1' && s[i - 1] != '2')
return 0;
else
ret[i + 1] = ret[i - 1];
}
else
{
if(s[i - 1] == '0' || s[i - 1] * 10 + s[i] - 11 * '0' > 26)
ret[i + 1] = ret[i];
else
ret[i + 1] = ret[i] + ret[i - 1];
}
}
return ret.back();
}
};
上面的解法对于情况的分类很清晰,但是代码看起来有点乱。参考了别人的方法将f(n)的值分为三类, 满足条件一(10<= val<=26)则结果必然有f(n-2),满足条件二(s[i] != '0')则结果必然有f(n-1),如果都不满足则不做操作,f(n)默认为0.因此在循环控制中加入判断,如果第i-1个解码方式为0,则接下来不必进行循环了。
代码如下:
class Solution {
public:
int numDecodings(string s) {
if(s.empty() || s[0] == '0')
return 0;
vector<int> ret(s.size() + 1, 0); //也可以用三个数来循环保存
ret[0] = ret[1] = 1;
for(int i = 1; ret[i - 1] && i < s.size(); i++) //如果i-1的解码方式为0 则直接退出
{
int val = 10 * (s[i - 1] - '0') + s[i] - '0';
if(val >= 10 && val <= 26)
ret[i + 1] += ret[i - 1];
if(s[i] != '0')
ret[i + 1] += ret[i];
}
return ret.back();
}
};