青训营X豆包 MarsCode AI|豆包MarsCode AI刷题

141 阅读4分钟

数字翻译成字符串的可能性| python解法

题目分析

本题是一个经典的动态规划问题,主要考察字符串处理与状态转移。题目要求将给定的数字翻译为字符串,翻译规则是:0 对应 "a"1 对应 "b",以此类推,25 对应 "z"。给定一个数字,求有多少种不同的翻译方式。例如,数字 12258 可以被翻译为 "bccfi", "bwfi", "bczi", "mcfi""mzi",共计 5 种不同的翻译方法。

解题思路

我们可以发现,问题本质上是如何将数字字符串分割成一个个子串,使得这些子串可以翻译成字母。要解决这个问题,可以有以下几种方法:

  1. 递归法:将字符串按字符逐一拆分或者按两字符拆分,利用递归方式探索所有可能的翻译方案。每次递归时,判断当前拆分是否符合翻译规则(即 025 之间),如果符合则继续拆分。这种方法简单但效率较低,容易导致重复计算和时间超时。
  2. 动态规划法:利用动态规划解决重复子问题。动态规划的核心思想是将问题分解为更小的子问题,逐步解决,并记录每一步的结果以便后续使用,避免重复计算。这个方法效率较高,是解本题的最佳方案。

基本思想

动态规划解决问题的基本步骤如下:

  1. 状态定义

    • 定义 dp[i] 为数字字符串的前 i 个字符的翻译方法总数。
  2. 状态转移方程

    • 如果第 i-1 个字符可以独立翻译(即不为 '0'),则 dp[i] += dp[i-1]
    • 如果第 i-2i-1 组成的两位数在 1025 之间,则 dp[i] += dp[i-2],这意味着这两位数可以作为一个整体翻译成一个字母。
  3. 初始化

    • dp[0] = 1,表示空字符串有一种翻译方法。
    • dp[1] = 1,表示单个字符有一种翻译方法。
  4. 结果

    • 最终结果为 dp[n],其中 n 是字符串的长度。

关键知识点总结

  • 动态规划

    • 动态规划适用于可以被分解为重复子问题的问题。它通过记录中间结果,避免重复计算,提高效率。
  • 字符串处理

    • 要判断两个字符组成的子串是否可以翻译,需要考虑其是否在 "10""25" 之间。
  • 边界条件

    • 数字中可能包含 0,在这种情况下需要特别处理,避免翻译错误。例如 "10" 可以翻译为 "j",但 "01" 不可翻译。

复杂度分析

  • 时间复杂度O(n),其中 n 是数字的长度。每个字符只需处理一次,没有重复计算。
  • 空间复杂度O(n),需要一个长度为 n+1 的数组存储动态规划结果。可以通过滚动数组优化为 O(1)

代码实现

def solution(num): 
    # 将输入数字转换为字符串,方便处理每一位数字 
    str_num = str(num) 
    n = len(str_num) 
    # 边界情况处理:如果字符串为空,返回 0;如果长度为 1,只有一种翻译方式 
    if n == 0: 
        return 0 
    if n == 1: 
        return 1 
        
    # 初始化 dp 数组 
    dp = [1, 1] # dp[0] = 1, dp[1] = 1 为基准,前两个字符的翻译方式 
    
    # 从第 2 个字符开始,逐步计算每个位置的翻译方法数 
    for i in range(2, n + 1): 
        dp_i = dp[i - 1] # 默认翻译当前字符 
        # 检查当前字符和前一个字符是否可以组成一个有效的两位数翻译 
        two_digit = int(str_num[i - 2:i]) # 提取当前和前一个字符形成的两位数 
        if 10 <= two_digit <= 25: 
            dp_i += dp[i - 2] # 如果两位数可以翻译,加入前两位的翻译方法数 
        dp.append(dp_i) # 将 dp[i] 加入数组 
    # 返回 dp[n],即整个字符串的翻译方法总数 
    return dp[-1] # 最终的翻译方法总数

扩展适用场景

这道题的解决方法可以推广到以下场景:

  1. 字母解码问题

    • 类似于 "Leetcode 91. 解码方法"(Decode Ways),其中每个数字代表一个字母(如 1 对应 "A"26 对应 "Z")。这道题也是通过动态规划求解,思路相似。
  2. 分割子字符串问题

    • 如果需要将字符串按特定规则分割为多个部分并统计分割方式,可以借鉴这种动态规划的思路。
  3. 拼音数字翻译

    • 类似地,如果题目要求将数字翻译为其他语言的字符或拼音,并且有一定的映射关系,也可以使用动态规划进行求解。

总结

本题的解题关键在于:

  • 使用动态规划避免重复计算,提高效率。
  • 合理处理数字的边界情况,尤其是包含 0 的情况。
  • 定义好状态转移方程,利用前面的计算结果递推得到最终解。