题目描述
小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(从 2 到 n),可以考虑两种情况:
- 只翻译当前字符
str[i-1],此时dp[i]增加dp[i-1]。 - 如果当前字符和前一个字符
str[i-2]可以组合成一个有效的数字(即在10到25之间),则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 的数组来存储每个状态的结果。