青训营刷题-7

138 阅读2分钟

7 数字翻译成字符串的可能性

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

输入格式

一个 int 型的数字,0 <= num <= 2 的 31 次方

输出格式

也是一个 int 型数字,代表字符串的总共可能性

输入样例

输入: 12258

输出样例

输出: 5

解释: 12258 有 5 种不同的翻译,分别是 "bccfi", "bwfi", "bczi", "mcfi" 和 "mzi"

解题思路

  1. 数字字符串的处理

    • 首先,将给定的数字转换为字符串形式,便于逐位处理。
    • 例如,数字 12258 转换为字符串 "12258"
  2. 动态规划的定义

    • 定义 dp[i] 表示字符串前 i 位的翻译方式数。
    • 目标是求出 dp[n],其中 n 是字符串的长度。
  3. 状态转移方程

    • 对于每一个位置 i,有两种可能的翻译方式:

      • 单个字符翻译

        • 将当前字符 s[i-1] 翻译为一个字母。
        • 此时 dp[i] += dp[i-1]
      • 两个字符组合翻译

        • 将当前字符 s[i-2]s[i-1] 组合成一个两位数,再翻译为一个字母。
        • 只有当组合后的两位数 10 <= num <= 25 时,才有这种翻译方式。
        • 此时 dp[i] += dp[i-2]
  4. 初始化

    • dp[0] = 1:空字符串有一种翻译方式。
    • dp[1] = 1:第一个字符有一种翻译方式(除非是无效的情况,如数字开头为 0,但根据题目描述,输入都是有效的)。
  5. 最终答案

    • dp[n] 即为整个字符串的翻译方式数。

算法实现

public class Main {
    public static int solution(int num) {
        // Please write your code here
        // 将数字转换为字符串,便于逐位处理
        String s = String.valueOf(num);
        int n = s.length();
        
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i=2;i<=n;i++){
            int currentDigit = s.charAt(i-1) - '0';
            int prevDigit = s.charAt(i-2) - '0';

            if(currentDigit >=0 && currentDigit <= 25){
                dp[i] += dp[i-1];
            }

            int twoDigits = prevDigit * 10 + currentDigit;
            if(twoDigits >= 10 && twoDigits <= 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);
    }
}