首页 > 其他 > 详细

leetcode---91.解码方法

时间:2021-04-23 00:09:38      阅读:19      评论:0      收藏:0      [点我收藏+]

题目描述

一条包含字母 A-Z 的消息通过以下映射进行了编码

‘A‘ -> 1
‘B‘ -> 2
...
‘Z‘ -> 26

解码已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

"AAJF",将消息分组为 (1 1 10 6)
"KJF",将消息分组为 (11 10 6)

注意,消息不能分组为(1 11 06),因为"06"不能映射为"F",这是由于"6"和"06"在映射中并不等价。
给你一个只含数字的非空字符串 s ,请计算并返回解码方法的总数
题目数据保证答案肯定是一个32位的整数。

示例

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6)。
输入:s = "06"
输出:0
解释:"06" 不能映射到 "F" ,因为字符串含有前导 0("6" 和 "06" 在映射中并不等价)。

解题思路

对于给定的字符串 s,设它的长度为 n,其中的字符从左到右依次为 s[1], s[2], ... , s[n]。我们可以使用动态规划的方法计算出字符串 s 的解码方法数。

具体地,设 \(dp[i]\) 表示字符串 \(s\) 地前 \(i\) 个字符 \(s[1,...,i]\) 的解码方法数。在进行状态转移时,我们可以考虑最后一次解码使用了 \(s\) 中的哪些字符,那么会有下面两种情况:

  • 第一种情况是我们使用了一个字符,即 \(s[i]\) 进行编码,那么只要 \(s[i] \neq 0\),它就可以被解码成相应的字母。由于剩余的前 \(i-1\) 个字符的解码方法书为 \(dp[i-1]\),因此我们可以写出状态转移方程:

\[dp[i]=dp[i-1], 其中s[i] \neq 0 \]

  • 第二种情况是我们使用了两个字符,即 \(s[i]\)\(s[i-1]\) 进行编码。与第一种情况类似,\(s[i-1]\)不能等于0,并且\(s[i]\)\(s[i-1]\)组成的整数必须小于等于26,这样他们可以被解码成对应的字母。由于剩余的前 \(i-2\) 个字符的解码方法数为 \(dp[i-2]\),因此我们可以写出状态转移方程:

\[dp[i]=dp[i-2], 其中s[i-1] \neq 0 并且10*s[i-1]+s[i]\leq26 \]

  • 需要注意的是,只有当 \(i>1\) 时才进行转移,否则\(dp[i-2]\) 不存在。

将上面的两种状态转移方程在对应的条件满足时进行累加,即可得到\(dp[i]\)的值。在动态规划完成后,最终答案即为\(dp[n]\)

  • 细节;动态规划的边界条件为:\(dp[0]=1\),即空字符串可以有一种解码方法,解码出一个空字符串。

代码1 使用数组进行状态转移

class Solution:
    def numDecodings(self, s: str) -> int:
        n = len(s)
        dp = [1] + [0]*n
        for i in range(1, n+1):

            # 逐位判断,如果当前位置不为‘0’,则当前位置为dp表中的值1
            if s[i-1] != ‘0‘:
                dp[i] += dp[i-1]

            # 如果前面一位不为‘0’,则前面一位可以和当前位置的数字组合 然后判断是否<26
            if i>1 and s[i-2] != ‘0‘ and int(s[i-2:i]) <= 26:
                dp[i] += dp[i-2]

        return dp[n]

代码1 复杂度

  • 时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)

代码2 使用三个变量进行状态转移

注意到在状态转移方程中,\(dp[i]\) 的值仅与 \(dp[i-1]\)\(dp[i-2]\) 有关,因此我们可以使用三个变量进行状态转移,省去数组的空间。

class Solution:
    def numDecodings(self, s: str) -> int:
        n = len(s)

        # a = dp[i-2], b = dp[i-1], c = dp[i]
        a, b, c = 0, 1, 0

        for i in range(1, n + 1):
            c = 0
            if s[i - 1] != ‘0‘:
                c += b
            if i > 1 and s[i - 2] != ‘0‘ and int(s[i-2:i]) <= 26:
                c += a
            a, b = b, c
        return c

代码1 复杂度

  • 时间复杂度 \(O(n)\),空间复杂度 \(O(1)\)

leetcode---91.解码方法

原文:https://www.cnblogs.com/kanka/p/14690807.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!