题目描述
给定一个数字,按照如下规则翻译成字符串:0翻译成“a”,1翻译成“b”…25翻译成“z”。一个数字有多种翻译可能,例如12258一共有5种,分别是bccfi,bwfi,bczi,mcfi,mzi。实现一个函数,用来计算一个数字有多少种不同的翻译方法。
解题思路
看到题目,很容易想到使用递归:用f(i)来表示从第i位开始的不同翻译数目,可以得到有:f(i)=f(i+1)+g(i,i+1)*f(i+2)。i和i+1位数字拼起来在10~25范围内时g(i,i+1)的值为1,否则为0。
但是存在重复的子问题,所以递归并非最佳方法,我们从数字的末尾开始计算f(i),自下而上解决问题,就可以消除重复的子问题了。先算f(len-1),f(len-2),再根据公式f(i)=f(i+1)+g(i,i+1)*f(i+2)往前逐步推导到f(0),这就是最终要求的结果。
算法图解
比较简单不做图了!
参考代码:
package offer
;
public class Offer46 {
public static void main(String
[] args
) {
int n
= 12258;
System
.out
.println(getTranslationCount(n
));
}
public static int getTranslationCount(int n
) {
if (n
< 0) return 0;
String ns
= String
.valueOf(n
);
return translation(ns
);
}
public static int translation(String ns
) {
if (Integer
.parseInt(ns
) < 0) {
return 0;
}
int len
= ns
.length();
int[] sum
= new int[ns
.length()];
int count
= 0;
for (int i
= ns
.length() - 1; i
>= 0; i
--) {
count
= 0;
if (i
< ns
.length() - 1) {
count
= sum
[i
+ 1];
} else {
count
= 1;
}
if (i
< ns
.length() - 1) {
int first
= ns
.charAt(i
) - '0';
int second
= ns
.charAt(i
+ 1) - '0';
int combine
= first
* 10 + second
;
if (combine
>= 10 && combine
<= 25) {
if (i
< ns
.length() - 2) {
count
+= sum
[i
+ 2];
} else {
count
+= 1;
}
}
}
sum
[i
] = count
;
}
return sum
[0];
}
}
附录
该题源码在我的 ?Github 上面!