数字翻译成字符串的可能性问题
问题描述
在这个问题中,我们的任务是将一个给定的数字翻译成字符串。翻译规则是:数字 0 到 25 分别对应字母 a 到 z,即 0 -> 'a', 1 -> 'b', ..., 25 -> 'z'。我们需要计算一个数字有多少种不同的翻译方法。
例如,对于数字 12258,我们可以得到以下几种翻译方法:
- "bccfi"
- "bwfi"
- "bczi"
- "mcf"
- "mzi"
因此,数字 12258 可以有 5 种不同的翻译方式。
解题思路
这个问题可以通过动态规划来解决。我们定义一个动态规划数组 dp[i],表示数字的前 i 位有多少种翻译方法。通过逐步考虑每一个位置的数字及其与前一位数字的组合情况,我们可以计算出总的翻译方式。
具体的动态规划过程如下:
-
初始化状态:
dp[0]表示空字符串的翻译方法,显然只有 1 种方法,即不翻译。dp[1]表示第一个数字的翻译方法,如果这个数字有效(即0-9),则dp[1] = 1,否则为 0。
-
状态转移:
- 对于每个位置
i,我们需要检查当前数字和前一个数字的组合:- 单独翻译:如果
num[i-1]是有效的(即0 <= num[i-1] <= 9),则dp[i]可以继承自dp[i-1]。 - 组合翻译:如果
num[i-2:i]组成的数字在10到25之间,说明这个两位数可以组成一个有效字母(如10-> 'k'),则dp[i]还可以继承自dp[i-2]。
- 单独翻译:如果
- 对于每个位置
-
最终答案:
dp[n]即为翻译完整个数字所需的翻译方法的总数。
动态规划算法步骤
-
初始化:
dp[0] = 1(空字符串有 1 种翻译方法)。dp[1] = 1(如果第一个数字有效)。
-
遍历:
- 从第二个字符开始,检查每个字符是否可以单独翻译,或者与前一个字符组合翻译。
-
返回结果:最终
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
代码解释
-
输入处理:
- 首先将输入的数字转换成字符串
num_str,这样便于逐位访问每个数字。
- 首先将输入的数字转换成字符串
-
动态规划数组初始化:
dp[0] = 1表示空字符串的翻译方法有 1 种。dp[1]根据第一个数字是否有效来决定。
-
动态规划更新:
- 对于每一位
i,我们首先检查当前单个数字是否有效,如果有效,则从前一个状态继承翻译方法。 - 然后,检查当前和前一位组合形成的两位数是否在有效范围内(即
10 <= two_digits <= 25),如果有效,则从前两个状态继承翻译方法。
- 对于每一位
-
返回结果:
- 最终,
dp[n]即为数字的翻译方法总数。
- 最终,
时间复杂度与空间复杂度
- 时间复杂度:
O(n),其中n是数字的长度。我们只需要一次遍历整个数字。 - 空间复杂度:
O(n),我们使用了一个大小为n + 1的动态规划数组。
测试案例
-
输入:
12258- 输出:
5。可以有 5 种不同的翻译方法。
- 输出:
-
输入:
1408112- 输出:
6。有 6 种翻译方式。
- 输出:
-
输入:
2110101- 输出:
10。该数字有 10 种翻译方法。
- 输出:
-
输入:
25- 输出:
2。可以翻译为 "b" 或 "z"。
- 输出:
-
输入:
1023- 输出:
4。该数字有 4 种翻译方式。
- 输出:
总结
这个问题使用动态规划有效地解决了数字翻译问题。通过逐位处理数字和组合翻译,我们能够计算出一个数字有多少种不同的翻译方法。该方法具有较高的时间效率和空间效率,适合大部分测试场景。