数字翻译成字符串的可能性 | 豆包MarsCode AI刷题
一开始只想到了用dfs进行分割情况讨论,没有想到动态规划,后面问了ai发现动态规划也可以很好处理。
题目有些缺漏点,对前导零没有很好的解释。例如:100012这种情况,0算一个,00算一个,那000呢?0001、00012?这里没有解释清楚。但是最多只看两位这个规则能过所有样例了,也就没有进一步纠结了,可能后续还会有调整吧。
摘要
本题要求将数字转换为字符串,数字翻译遵循特定规则:0 对应 a,1 对应 b,以此类推,直到 25 对应 z。需要计算给定数字的所有可能翻译方法数量。本问题可以通过动态规划(Dynamic Programming, DP)高效解决。
问题描述
给定一个整数,将其翻译为字母,规则如下:
0对应a,1对应b,直到25对应z。- 每个数字可以单独翻译为一个字母,也可以将两个连续的数字组合翻译为一个字母(前提是该两位数在
[10, 25]范围内)。
需要计算出所有可能的翻译方法的数量。
测试样例
样例 1
输入:num = 12258
输出:5
样例 2
输入:num = 1400112
输出:6
样例 3
输入:num = 2110101
输出:10
样例 4
输入:num = 25
输出:2
样例 5
输入:num = 1023
输出:4
算法原理
动态规划(DP)核心思路:
-
定义状态:
定义dp[i]表示以第i个数字结尾的子序列的翻译方法总数。 -
状态转移方程:
- 如果当前数字单独翻译:
- 如果当前数字和前一个数字可以组合翻译(两位数在
[10, 25]范围内):
- 如果当前数字单独翻译:
-
边界条件:
dp[0] = 1:第一个数字只有一种翻译方式。dp[1] = 2(如果前两个数字能组成一个合法的两位数);否则dp[1] = 1。
-
最终结果:
dp[n-1]为数字num的翻译方法总数。
时间复杂度和空间复杂度分析
- 时间复杂度:,其中 为数字的位数。我们只需遍历数字一次即可完成计算。
- 空间复杂度:,需要一个长度为 的数组存储
dp状态。但可以通过优化实现 空间复杂度。
Go代码
package main
import (
"fmt"
"strconv"
)
func solution(num int) int {
// 将数字转为字符串
numStr := strconv.Itoa(num)
n := len(numStr)
// 如果数字只有一位,只有一种翻译方式
if n == 1 {
return 1
}
// 初始化动态规划数组
dp := make([]int, n)
dp[0] = 1 // 第一个数字只有一种翻译方式
// 判断前两个数字是否可以组成合法的两位数
if isValidTwoDigit(numStr[0:2]) {
dp[1] = 2 // 前两个数字可以单独翻译,也可以组合翻译
} else {
dp[1] = 1 // 前两个数字只能单独翻译
}
// 动态规划填表
for i := 2; i < n; i++ {
// 单独翻译当前数字
dp[i] = dp[i-1]
// 检查是否可以组合翻译
if isValidTwoDigit(numStr[i-1 : i+1]) {
dp[i] += dp[i-2]
}
}
return dp[n-1]
}
// 辅助函数:判断两个字符是否可以组成合法的两位数(10 <= x <= 25)
func isValidTwoDigit(s string) bool {
if len(s) != 2 {
return false
}
if s[0] == '0' { // 两位数不能以 0 开头
return false
}
num, _ := strconv.Atoi(s)
return num >= 10 && num <= 25
}
func main() {
// You can add more test cases here
fmt.Println(solution(12258) == 5)
fmt.Println(solution(1400112) == 6)
fmt.Println(solution(2110101) == 10)
}
Python代码
def solution(num):
"""
将数字转化为字符串,根据规则计算有多少种翻译方法。
- 每一位数字可以单独翻译。
- 两位数字如果在 10-25 范围内,可以组合翻译。
"""
# 将数字转换为字符串
num_str = str(num)
n = len(num_str)
# 如果只有一位数字,只有一种翻译方式
if n == 1:
return 1
# 初始化动态规划数组
dp = [0] * n
dp[0] = 1 # 第一个数字只有一种翻译方式
# 判断前两个数字是否可以组合翻译
if is_valid_two_digit(num_str[0:2]):
dp[1] = 2 # 可以单独翻译或组合翻译
else:
dp[1] = 1 # 只能单独翻译
# 动态规划填表
for i in range(2, n):
# 单独翻译当前数字
dp[i] = dp[i - 1]
# 检查是否可以组合翻译
if is_valid_two_digit(num_str[i - 1 : i + 1]):
dp[i] += dp[i - 2]
return dp[-1]
def is_valid_two_digit(s):
"""
判断两位数字是否在 10 到 25 之间。
"""
if len(s) != 2 or s[0] == '0': # 排除非法情况
return False
num = int(s)
return 10 <= num <= 25
if __name__ == "__main__":
# You can add more test cases here
print(solution(12258) == 5)
print(solution(1400112) == 6)
print(solution(2110101) == 10)