数字翻译成字符串的可能性问题

42 阅读4分钟

数字翻译成字符串的可能性问题

问题描述

在这个问题中,我们的任务是将一个给定的数字翻译成字符串。翻译规则是:数字 025 分别对应字母 az,即 0 -> 'a', 1 -> 'b', ..., 25 -> 'z'。我们需要计算一个数字有多少种不同的翻译方法。

例如,对于数字 12258,我们可以得到以下几种翻译方法:

  • "bccfi"
  • "bwfi"
  • "bczi"
  • "mcf"
  • "mzi"

因此,数字 12258 可以有 5 种不同的翻译方式。

解题思路

这个问题可以通过动态规划来解决。我们定义一个动态规划数组 dp[i],表示数字的前 i 位有多少种翻译方法。通过逐步考虑每一个位置的数字及其与前一位数字的组合情况,我们可以计算出总的翻译方式。

具体的动态规划过程如下:

  1. 初始化状态

    • dp[0] 表示空字符串的翻译方法,显然只有 1 种方法,即不翻译。
    • dp[1] 表示第一个数字的翻译方法,如果这个数字有效(即 0-9),则 dp[1] = 1,否则为 0。
  2. 状态转移

    • 对于每个位置 i,我们需要检查当前数字和前一个数字的组合:
      • 单独翻译:如果 num[i-1] 是有效的(即 0 <= num[i-1] <= 9),则 dp[i] 可以继承自 dp[i-1]
      • 组合翻译:如果 num[i-2:i] 组成的数字在 1025 之间,说明这个两位数可以组成一个有效字母(如 10 -> 'k'),则 dp[i] 还可以继承自 dp[i-2]
  3. 最终答案dp[n] 即为翻译完整个数字所需的翻译方法的总数。

动态规划算法步骤

  1. 初始化

    • dp[0] = 1(空字符串有 1 种翻译方法)。
    • dp[1] = 1(如果第一个数字有效)。
  2. 遍历

    • 从第二个字符开始,检查每个字符是否可以单独翻译,或者与前一个字符组合翻译。
  3. 返回结果:最终 dp[n] 就是我们要求的结果。

代码实现

def solution(num):
    num_str = str(num)  # 将数字转换为字符串,便于逐位访问
    n = len(num_str)
    
    # 动态规划数组,dp[i]表示前i个字符的翻译方式
    dp = [0] * (n + 1)
    dp[0] = 1  # 空字符串有1种翻译方法
    
    # 第一个字符的翻译方法
    dp[1] = 1 if num_str[0] != '0' else 0
    
    for i in range(2, n + 1):
        # 处理单个字符
        single_digit = int(num_str[i - 1])
        if 0 <= single_digit <= 9:
            dp[i] += dp[i - 1]
        
        # 处理两个字符的组合
        two_digits = int(num_str[i - 2:i])
        if 10 <= two_digits <= 25:
            dp[i] += dp[i - 2]
    
    return dp[n]

# 测试样例
print(solution(12258))  # 输出: 5
print(solution(1408112))  # 输出: 6
print(solution(2110101))  # 输出: 10
print(solution(25))  # 输出: 2
print(solution(1023))  # 输出: 4

代码解释

  1. 输入处理

    • 首先将输入的数字转换成字符串 num_str,这样便于逐位访问每个数字。
  2. 动态规划数组初始化

    • dp[0] = 1 表示空字符串的翻译方法有 1 种。
    • dp[1] 根据第一个数字是否有效来决定。
  3. 动态规划更新

    • 对于每一位 i,我们首先检查当前单个数字是否有效,如果有效,则从前一个状态继承翻译方法。
    • 然后,检查当前和前一位组合形成的两位数是否在有效范围内(即 10 <= two_digits <= 25),如果有效,则从前两个状态继承翻译方法。
  4. 返回结果

    • 最终,dp[n] 即为数字的翻译方法总数。

时间复杂度与空间复杂度

  • 时间复杂度O(n),其中 n 是数字的长度。我们只需要一次遍历整个数字。
  • 空间复杂度O(n),我们使用了一个大小为 n + 1 的动态规划数组。

测试案例

  1. 输入12258

    • 输出5。可以有 5 种不同的翻译方法。
  2. 输入1408112

    • 输出6。有 6 种翻译方式。
  3. 输入2110101

    • 输出10。该数字有 10 种翻译方法。
  4. 输入25

    • 输出2。可以翻译为 "b" 或 "z"。
  5. 输入1023

    • 输出4。该数字有 4 种翻译方式。

总结

这个问题使用动态规划有效地解决了数字翻译问题。通过逐位处理数字和组合翻译,我们能够计算出一个数字有多少种不同的翻译方法。该方法具有较高的时间效率和空间效率,适合大部分测试场景。