LeetCode:91. 解码方法(python)
一条包含字母 A-Z 的消息通过以下方式进行了编码:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例 1:
输入: “12”
输出: 2
解释: 它可以解码为 “AB”(1 2)或者 “L”(12)。
示例 2:
输入: “226”
输出: 3
解释: 它可以解码为 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。
思路:动态规划
-
状态:从字符串头部遍历至尾部
-
选择:罗列
s[i]
字符的解码值情况,dp[i]
保存字符串从头部到i
位置解码的总数。-
考虑
i
处字符与i-1
处字符结合,主要分析0
字符的不同情况:- 若为
00
或30、40、50...
则无法解码,可直接返回0
; - 若为
01~09
的情况,则i
处字符不能与前一位结合,则只有单字符解码的情况,即dp[i]=dp[i-1]
; - 若为
10、20
的情况,则i
处字符必须与前一位结合,则为双字符解码,即dp[i]=dp[i-2]
; - 若为
11~19、21~26
的情况,则i
处字符既可以单字符解码,也可以双字符解码,因此dp[i]=dp[i-2]+dp[i-1]
; - 剩余为
27~29、31~39、41~49...
的情况只可以单字符解码,即dp[i]=dp[i-1]
。
- 若为
-
图示如下:
-
-
遍历:判断
i
处字符解码情况需要考虑前一位字符,因此从字符串i=1
处开始遍历。 -
初始化:
- 字符串从
i=1
处开始遍历,该字符处可单字符解码和双字符解码的方法数都为1
,即dp[i-2]=1、dp[i-1]=1
,则多添加一位数方便计算,设置dp=[1,1]
。
- 字符串从
附代码(Python3):
class Solution:
def numDecodings(self, s):
if not s or s[0]=='0': # s 为空或 s 头部为 '0' 则返回 0
return 0
dp = [1, 1] # 初始化 dp
for i in range(1, len(s)):
if s[i-1:i+1] == '00' or (s[i]=='0' and s[i-1]>'2'): # 直接返回 0 的情况(00、30、40....)
return 0
if '1'<=s[i-1:i+1]<='26' and s[i]!='0': # 可单字符和双字符解码的情况(11~19、21~26)
dp.append(dp[-2]+dp[-1])
elif s[i]=='0': # 只能双字符解码的情况(10、20)
dp.append(dp[-2])
else:
dp.append(dp[-1]) # 只能单字符解码的情况(01~09、27~29、31~39...)
return dp[-1]
test = Solution()
s_li = ["12", "226", "24726"]
for s in s_li:
print(test.numDecodings(s))