您的位置:首页 > 其它

Decode Ways - LeetCode

2015-11-04 10:54 260 查看
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.

思路:DP。这题依旧可以保持O(1)的空间复杂度。

先考虑字符串最普遍的情况,假设有字符串S1S2S3, 假设我们已经考虑到了S3,则S3有2种情况:

1)S2S3可以组成10-26, 设dp[2]为到S3位置所有可能的情况,则dp[2] = dp[0] + dp[1]。

先解释下这个公式为什么会成立,dp[0]为S1可能的解读情况,而当S2和S3各自单独解读为一个字母时,可能情况并没有增加,还是dp[0]。再考虑dp[1],它是截止到S2可能的解读情况,排除掉之前dp[0]时各自单独解读的情况,这里有两种可能:S1S2可以构成10-26,S3自己单独解读(可能情况数等于S1S2一起解读时的情况数),或者S2S3解读为10-26(可能情况数等于S2单独解读时的情况数),两者加起来正好是截止到S2的可能情况总数,即dp[1]。将上述情况进行综合得dp[2] = dp[0] + dp[1]。

2)S2S3不能组合成10-26, 则相当于在截止于S2的所有可能情况后面都额外加了一个无关紧要的S3,并没有增加额外的情况,因此dp[2] = dp[1]。

还有一点要注意的是,如果S3为0,则要么必需和S2组合到一起解读,要么整个字符串是非法的。因为单独一个0无法解读。因此,当S3为0时,dp[2] = dp[1]。而此时无法和S2组合,也就是非法的情况,我们在下面的实现方法中说明。

实现:我们维护两个值,preslow和prefast。

假设当前我们到了Si,则preslow为截止到Si-2时的情况数,prefast为截止到Si-1时的情况数。

先判断当前Si是否为0,若是,则令prefast = 0。

若Si能和Si-1构成10-26, 则领prefast = prefast + preslow;preslow = prefast - preslow。

这里可以看到,如果当前Si为0的话,prefast为0,则prefast=prefast + preslow将为preslow,即截止到si-2时的可能情况,与我们上面讨论的结果一致。否则就是dp[i -2] + dp[i - 1]。这样计算完之后,prefast已经更新到了截止于Si的值,因此preslow也往前移一位,得到之前Si-1的值。

如果Si不能和Si-1构成10-26,则dp[i] = dp[i-1],这里就是保持prefast值不变。而preslow仍要前移一位,值也要更新为prefast。这里要注意到,假如Si为0,则prefast当前已经为0,而在当前情况下这个字符串是非法的。经过这一步后,preslow也变成了0。所以之后不管怎么样,两个变量的值都将永远是0。

最后,prefast的值即为结果。

class Solution {
public:
int numDecodings(string s) {
int n = s.size();
if (n < 1 || s[0] == '0') return 0;
int preslow = 1, prefast = 1;
for (int i = 1; i < n; i++)
{
if (s[i] == '0') prefast = 0;
if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] < '7'))
{
prefast = preslow + prefast;
preslow = prefast - preslow;
}
else preslow = prefast;
}
return prefast;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: