给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 2^31
解题思路:
法1:递归思路。将数字转换为字符串,从0位开始,如果第i位和第i+1位能够组合(即两数组合值小于26),则递归调用两次函数,形参分别是i+1和i+2,计数器+1;如果第i位和第i+1位不能组合,则递归调用一次函数,形参是i+1。递归函数终止条件是i指向字符串最末位,最终返回计数。
class Solution {
int ret = 1;
public int translateNum(int num) {
char[] charray = String.valueOf(num).toCharArray();
translate(charray, 0, charray.length);
return ret;
}
public void translate(char[] charray, int i, int len){
if(i == len) return;
if(charray[i] != '0' && i + 1 < len && (charray[i] - 48) * 10 + (charray[i+1] - 48) < 26){
translate(charray, i + 1, len);
translate(charray, i + 2, len);
ret++;
}
else{
translate(charray, i + 1, len);
}
}
}
注意:当字符是0时也不能和下一个字符组合,需要判断i+1是否超出了字符串的边界。
法2:动态规划。计算前i位的组合方法数,动态更新到最后一位,转移方程是:
class Solution{
public int translateNum(int num){
char[] charray = String.valueOf(num).toCharArray();
int len = charray.length;
int p = 1;
int q = 1;
int ret = 1;
for(int i = 1; i < len; i++){
if(charray[i-1] != '0' && (charray[i-1] - 48) * 10 + (charray[i] - 48) < 26){
ret = p + q;
}
p = q;
q = ret;
}
return ret;
}
}