青训营—数字翻译成字符串的可能性

162 阅读2分钟

题目描述

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

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

测试样例

样例1

输入:num = 12258
输出:5

样例2

输入:num = 1400112
输出:6

样例3

输入:num = 2110101
输出:10

样例4

输入:num = 25
输出:2

样例5

输入:num = 1023
输出:4

思路

可以使用动态规划来解决这个问题。定义一个动态规划数组 dp,其中 dp[i] 表示前 i 个字符的翻译方式总数。

状态转移:

对于每个字符 i(从 2n),可以考虑两种情况:

  • 只翻译当前字符 str[i-1],此时 dp[i] 增加 dp[i-1]
  • 如果当前字符和前一个字符 str[i-2] 可以组合成一个有效的数字(即在 1025 之间),则 dp[i] 还需要增加 dp[i-2]

Java代码

public class Main {
    public static int solution(int num) {
        // Please write your code here
        String str = String.valueOf(num); // 将数字转成字符串
        int n = str.length();
 
        if (n == 0) return 0;
        if (n == 1) return 1; // 单字符的情况
 
        // 动态规划数组
        int[] dp = new int[n + 1];
        dp[0] = 1; // 空字符串一种方式
        dp[1] = 1; // 一个字符也有一种方式
 
        for (int i = 2; i <= n; i++) {
            // 只翻译当前字符
            dp[i] = dp[i - 1];
 
            // 结合前一个字符一起翻译
            int twoDigit = Integer.parseInt(str.substring(i - 2, i)); // 当前字符及前一个字符形成的数
            if (twoDigit >= 10 && twoDigit <= 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);
    }
}

复杂度分析

时间复杂度:O(n),其中 n 是输入数字的位数。只需遍历一次字符串来填充动态规划数组。

空间复杂度:O(n),使用了一个大小为 n+1 的数组来存储每个状态的结果。