数字翻译成字符串的可能性 | 豆包MarsCode AI刷题

116 阅读4分钟

数字翻译成字符串的可能性 | 豆包MarsCode AI刷题

数字翻译成字符串的可能性 - MarsCode

一开始只想到了用dfs进行分割情况讨论,没有想到动态规划,后面问了ai发现动态规划也可以很好处理。

题目有些缺漏点,对前导零没有很好的解释。例如:100012这种情况,0算一个,00算一个,那000呢?0001、00012?这里没有解释清楚。但是最多只看两位这个规则能过所有样例了,也就没有进一步纠结了,可能后续还会有调整吧。

摘要

本题要求将数字转换为字符串,数字翻译遵循特定规则:0 对应 a1 对应 b,以此类推,直到 25 对应 z。需要计算给定数字的所有可能翻译方法数量。本问题可以通过动态规划(Dynamic Programming, DP)高效解决。


问题描述

给定一个整数,将其翻译为字母,规则如下:

  • 0 对应 a1 对应 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)核心思路:

  1. 定义状态
    定义 dp[i] 表示以第 i 个数字结尾的子序列的翻译方法总数。

  2. 状态转移方程

    • 如果当前数字单独翻译:
      dp[i]=dp[i1]dp[i] = dp[i-1]
    • 如果当前数字和前一个数字可以组合翻译(两位数在 [10, 25] 范围内):
      dp[i]+=dp[i2]dp[i] += dp[i-2]
  3. 边界条件

    • dp[0] = 1:第一个数字只有一种翻译方式。
    • dp[1] = 2(如果前两个数字能组成一个合法的两位数);否则 dp[1] = 1
  4. 最终结果
    dp[n-1] 为数字 num 的翻译方法总数。


时间复杂度和空间复杂度分析
  • 时间复杂度O(n)O(n),其中 nn 为数字的位数。我们只需遍历数字一次即可完成计算。
  • 空间复杂度O(n)O(n),需要一个长度为 nn 的数组存储 dp 状态。但可以通过优化实现 O(1)O(1) 空间复杂度。

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)