题目内容
小M获得了一个任务,需要将数字翻译成字符串。翻译规则是:0对应"a",1对应"b",依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的翻译方法。
例如:数字 12258 可以翻译成 "bccfi", "bwfi", "bczi", "mcfi" 和 "mzi",共5种方式。
题目分析
这道题的主要思想是用动态规划求解方案数,用 AI 是基本可以直接得到答案的。但是我在使用 AI 时,它很奇怪地认为 0 不能翻译成字符?
定义状态
我们定义一个数组 dp,其中 dp[i] 表示前 i 个数字的翻译方法数量。注意,dp[0] 初始化为 1,因为空字符串有 1 种翻译方法。
状态转移
dp[i] 的值可以通过以下两种情况来计算:
-
当前数字一定可以单独翻译成一个字母:
dp[i]可以加上dp[i-1]。
-
当前数字和前一个数字可以组合翻译成一个字母:
- 如果当前数字和前一个数字的组合(即
num_str[i-2:i])在10到25之间,那么它们可以组合翻译成一个字母,dp[i]可以加上dp[i-2]。
- 如果当前数字和前一个数字的组合(即
通过动态规划的方法,我们可以以 的时间复杂度有效地计算出数字的不同翻译方法数量。
状态转移过程示例
让我们通过一个具体的例子来理解状态转移过程:
假设输入数字为 12258。
| 数字 | 空 | 1 | 12 | 122 | 1225 | 12258 |
|---|---|---|---|---|---|---|
dp[i] | 1 | 1 | 2 | 3 | 5 | 5 |
-
初始状态:
dp[0] = 1(空字符串有 1 种翻译方法) -
第一个数字
1:- 可以单独翻译成 "b",所以
dp[1] = dp[0] = 1。
- 可以单独翻译成 "b",所以
-
第二个数字
2:- 可以单独翻译成 "c",所以
dp[2] = dp[1] = 1。 - 可以和前一个数字
1组合翻译成 "l"(12),所以dp[2] += dp[0] = 1 + 1 = 2。
- 可以单独翻译成 "c",所以
-
第三个数字
2:- 可以单独翻译成 "c",所以
dp[3] = dp[2] = 2。 - 可以和前一个数字
2组合翻译成 "w"(22),所以dp[3] += dp[1] = 2 + 1 = 3。
- 可以单独翻译成 "c",所以
-
第四个数字
5:- 可以单独翻译成 "f",所以
dp[4] = dp[3] = 3。 - 可以和前一个数字
2组合翻译成 "z"(25),所以dp[4] += dp[2] = 3 + 2 = 5。
- 可以单独翻译成 "f",所以
-
第五个数字
8:- 可以单独翻译成 "i",所以
dp[5] = dp[4] = 5。 - 不能和前一个数字
5组合翻译成一个字母(因为组合58不在10到25之间),所以dp[5]不变。
- 可以单独翻译成 "i",所以
最终,dp[5] 的值为 5,表示数字 12258 有 5 种不同的翻译方法。
参考代码
def solution(num):
# 将数字转换为字符串以便于处理
num_str = str(num)
n = len(num_str)
# 初始化动态规划数组
dp = [0] * (n + 1)
# 初始条件:空字符串有1种翻译方法
dp[0] = 1
# 遍历字符串
for i in range(1, n + 1):
# 当前数字可以单独翻译成一个字母
dp[i] = dp[i-1]
# 如果当前数字和前一个数字可以组合翻译成一个字母
if i > 1 and '10' <= num_str[i-2:i] <= '25':
dp[i] += dp[i-2]
return dp[n]