返回

巧解「力扣」639 题:化繁为简,解码无忧

人工智能

「力扣」639 题简介

「力扣」第 639 题要求你计算一个字符串中不同解码方法的数量。字符串由数字组成,每个数字可以解码成对应的英文字母。例如,"1" 可以解码为 "a","2" 可以解码为 "b",以此类推。

但本题有一个额外的复杂性:字符串中可能包含通配符 '*'。通配符可以表示任何一个数字,因此它可以扩展解码的可能性。

化繁为简的解题思路

乍一看,这道题似乎非常复杂,但实际上,我们可以通过一个巧妙的思路将其化繁为简。

首先,我们将字符串分成两个部分:无通配符部分通配符部分 。对于无通配符部分,我们可以直接应用「力扣」第 90 题的解法。

「力扣」90 题回顾

在「力扣」第 90 题中,我们定义了一个动态规划数组 dpdp[i] 表示字符串的前 i 个字符的解码方法数量。我们可以使用以下公式来更新 dp 数组:

dp[i] = dp[i-1] + dp[i-2]

其中,dp[i-1] 表示前 i-1 个字符的解码方法数量,dp[i-2] 表示前 i-2 个字符的解码方法数量。

通配符部分的处理

对于通配符部分,我们可以将其分为两种情况:

  • 通配符单独出现: 在这种情况下,通配符可以表示任何一个数字,因此它可以扩展为 9 种解码方法('a' 到 'i')。
  • 通配符与数字一起出现: 在这种情况下,通配符可以表示任何一个数字,但它必须与前面的数字一起解码。例如,"2*" 可以解码为 "ab"、"ac"、"ad" 等。

完整解法

综上所述,我们可以得到以下完整的解法:

  1. 定义动态规划数组 dp
  2. 对于无通配符部分,直接应用「力扣」第 90 题的解法。
  3. 对于通配符部分,根据通配符的出现情况进行处理。
  4. 将无通配符部分和通配符部分的解码方法数量相乘,得到最终结果。

代码示例

def numDecodings(s: str) -> int:
    # 初始化动态规划数组
    dp = [0] * (len(s) + 1)
    # 无通配符部分的解码方法数量
    dp[0] = 1
    if s[0] != '*':
        dp[1] = 1

    # 遍历字符串
    for i in range(2, len(s) + 1):
        if s[i-1] != '*':
            dp[i] += dp[i-1]
        if s[i-2] != '*' and (s[i-2] == '1' or (s[i-2] == '2' and s[i-1] <= '6')):
            dp[i] += dp[i-2]
        if s[i-1] == '*':
            dp[i] += 9 * dp[i-1]
        if s[i-2] == '*' and s[i-1] == '*':
            dp[i] += 15 * dp[i-2]
            if s[i-3] == '1':
                dp[i] += 9 * dp[i-3]
            elif s[i-3] == '2' and s[i-1] <= '6':
                dp[i] += 6 * dp[i-3]

    # 返回最终结果
    return dp[len(s)]

总结

通过将字符串分成无通配符部分和通配符部分,并巧妙地处理通配符的情况,我们可以将「力扣」第 639 题这道困难的解码难题化繁为简。希望本文提供的解题思路能帮助你轻松破解这道难题!