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.
采用动态规划来解决,假设知道对于字符串s,从位置0解析到n-1和n-2时的解法数d[n-1]和d[n-2],那对于第n个字符就会有以下几种情况:
1.s[n]为0,且它与s[n-1]的组合是违法的,那s[n] = 0;
2.s[n]为0,但它与s[n-1]是合法组合,那s[n] = s[n-2];
3.s[n]不为0,且它与s[n-1]是合法组合,那s[n] = s[n-1] + s[n-2];
4.s[n]不为0,但它与s[n-1]的组合是违法的,那s[n] = s[n-1]
具体代码实现如下:
<pre name="code" class="cpp">class Solution {
public:
static int numDecodings(string s) {
if (s.empty() || s[0] == '0')
return 0;
if (s.size() == 1)
return 1;
//第一个字符肯定是合法的数字,只有一种解法
int preSecond = 1;
int preOne = 0;
if (canCompose(s[0], s[1]) && s[1] != '0')
preOne = 2;
else if ((canCompose(s[0], s[1]) && s[1] == '0') //第二个字符为0,只能与第一个字符组合
|| (!canCompose(s[0], s[1]) && s[1] != '0') //第二个字符不为0,但不能与第一个字符组合,只能分开解析
)
preOne = 1;
else //无论如何前两个字符都无解
return 0;
for (int i = 2; i < s.size(); ++i)
{
if (s[i] == '0')
{
if (canCompose(s[i - 1], s[i]))
//情况1
std::swap(preOne, preSecond);
else
//情况2
return 0;
}
else if (canCompose(s[i - 1], s[i]))
{
//情况3
preOne += preSecond;
preSecond = preOne - preSecond;
}
else
//情况4
preSecond = preOne;
}
return preOne;
}
private:
static bool canCompose(char chPre, char chPost)
{
if (chPre == 0)
return false;
if (chPre == '1' || (chPre == '2' && chPost <= '6'))
return true;
return false;
}
};