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的方法,但是需要注意的是细节,主要是0的存在是个大坑。
1.首先定义dp[i] 为字符串前i 个字母可以组成的方案数。
2.考虑转换方程:(1)如果当前字符可以单独组成一种情况,则dp[i] += dp[i-1](即s[i-1] != '0')
(2)如果当前字符可以和前一个字符一起组成一个数字,则dp[i] += dp[i-2](即当前数字和前一位数字组成的数大于9,小于27)
(3)如果当前字符为0无法单独组成一个数字,且又无法和前面一位数字一块构成,如30,40,00,则直接返回0
代码如下:
class Solution(object): def numDecodings(self, s): """ :type s: str :rtype: int """
#时间复杂度O(n),空间复杂度O(n),可以压缩为前一个,前两个的O(1)空间复杂度。
if not s: return 0 num = map(int, list(s)) dp = [0] * (len(s)+1) #the types of the first i number dp[0] = 1 if num[0] == 0: return 0 dp[1] = 1 for i in xrange(2, len(s) + 1): v = num[i-2]*10 + num[i-1] if v > 9 and v < 27: dp[i] += dp[i-2] if num[i-1] != 0: dp[i] += dp[i-1] if dp[i] == 0: return 0 return dp[-1]
原始的神智不清的解法是:
class Solution(object): def numDecodings(self, s): """ :type s: str :rtype: int """ if not s: return 0 num = map(int, list(s)) dp = [0] * (len(s)+1) #the types of the first i number dp[0] = 1 if num[0] == 0: return 0 dp[1] = 1 for i in xrange(2, len(s) + 1): if num[i-1] == 0: if num[i-2] > 0 and num[i-2] < 3: dp[i] = dp[i-2] else: return 0 else: dp[i] = dp[i-1] if num[i-2] != 0 and num[i-2] * 10 + num[i-1] < 27: dp[i] += dp[i-2] return dp[-1]