LeetCode:91. 解码方法(python)

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) 。

LeetCode 链接


思路:动态规划

  • 状态:从字符串头部遍历至尾部

  • 选择:罗列 s[i] 字符的解码值情况,dp[i] 保存字符串从头部到 i 位置解码的总数。

    • 考虑 i 处字符与 i-1 处字符结合,主要分析 0 字符的不同情况:

      • 若为 0030、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]
    • 图示如下:

      LeetCode:91. 解码方法(python)_第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))

你可能感兴趣的:(LeetCode,LeetCode,91.,解码方法,python)