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

54 阅读3分钟

题目指路-->数字翻译成字符串的可能性 - MarsCode

问题描述

小M获得了一个任务,需要将数字翻译成字符串。翻译规则是:0对应"a",1对应"b",依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的翻译方法。

例如:数字12258可以翻译成 "bccfi", "bwfi", "bczi", "mcfi" 和 "mzi",共5种方式。


测试样例

样例1:

输入:num = 12258
输出:5

翻译结果可以取[1,2,3,5,8]、[1,22,5,8]、[1,2,25,8]、[12,2,5,8]、[12,25,8]共五种情况。

样例2:

输入:num = 1400112
输出:6

样例3:

输入:num = 2110101
输出:10

解题思路:

通过阅读题目可以发现,翻译数字的位数不是一位就是两位,而到第i个数字为止可以翻译的方法数,是基于前面数字的翻译状态所决定的。所以,这个问题的本质就是通过动态规划,计算一个数字可以被翻译成多少种不同的字符串。

动态规划的核心思想

  1. 状态定义: 定义 dp[i] 表示从数字的第 i 位开始到最后一位可以有多少种翻译方法。

  2. 递推公式

  • 默认情况下,最后一位数字单独翻译成一个字母,对应的翻译方法和 dp[i-1] 相同。
  • 如果第 i-1 和第 i 位的数字可以组成有效的字母(即在 10 到 25 之间),则需要额外加上 dp[i-2] 对应的翻译方法数:

dp[i]=dp[i−1]+dp[i−2]

  • 如果不满足两位数字的条件(如大于 25 或小于 10),则 dp[i] = dp[i-1]
  1. 初始化
  • dp[0] = 1:空串只有一种翻译方法。
  • dp[1] = 1:只有一位数时的翻译方法只有 1 种。
  1. 边界条件

    • 如果输入的数字是 0 开头的,需要特殊处理,因为数字不能从 0 开头。

完整代码:

//动态规划
public class Main {
    public static int solution(int num) {
        // Please write your code here
        // n个数字共有dp[n]种翻译方法
        String str = Integer.toString(num);
        int n = str.length();

        if (n == 1) return 1;// 只有一位数

        int[] dp = new int[n + 1];
        dp[0] = 1;//空串的翻译方法有1种
        dp[1] = 1;//一位数的翻译方法有1种

        for (int i = 2; i <= n; i++) {
            //当前遍历到第i个数字
            //先默认最后两位无法组成字母,最后一位单独组成字母时
            //当前翻译方法=前一位翻译方法
            dp[i] = dp[i - 1];
            // 截取第i-1和第i个数字组成的字符串A
            //str下标是从0开始的
            String A = str.substring(i - 2, i);
            // 将字符串A转换成数字
            int B = Integer.valueOf(A);
            //如果当前数字可以和前一个数字组成字母
            //则需要加上第i-2位的翻译方法
            if (B >= 10 && B <= 25) {
                dp[i] += dp[i - 2];
            }
        }

        return dp[n];
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution(12258) == 5);
        System.out.println(solution(1400112) == 6);
        System.out.println(solution(2110101) == 10);
    }
}