题目:给定一个数字,我们按照如下规则把它翻译为字符串:0翻译成“a”,1翻译成“b”,……,11翻译成“l”,……,25翻译成“z”。一个数字可能有多个翻译。例如,12258有5种不同的翻译,分别是“bccfi”、“bwfi”、“bczi”、“mcfi”和“mzi”。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
思路:到最后感觉就是一道找规律的题目。使用动态规划解题。。。
先看一张图:
使用上述递归方式的话,会有很多重复的子运算,入两边都会子弟规258这个数字。
那么正题就来了,使用动态规划优化下就欧了。
我们通过找规律发现:f(i) = f(i+1)+g(1+1,i+2)*f(i+2),代表从当前位置开始至最后一位,存在几种组合,g(i+!,i+2)代表第i+1与i+2个数拼接到一起是不是在10~25这个范围内。先别蒙我举个例子解释下就感觉很简单了。
就拿题中给的数来说12258:这里的i代表索引值index
f(4) = 1种 8->i
f(3) = 1种 58->fi
f(2) = 2种 258->cfi/zi
f(1) = 3种 2258->wfi/ccfi/czi
f(0) = 5种 12258->mzi/bwfi/bccfi/mcfi/bczi
好了,从上边找到的规律就是f(i) = f(i+1)+g(1+1,i+2)*f(i+2)了
public int getNemberCount(int number){
if(number<0) return 0;
String numberS = String.valueOf(number);
int length = numberS.length();
int [] counts= new int[length];
for (int i=length-1;i>=0;i--){
if(i==length-1) {
counts[i] = 1;
}else {
counts[i] =counts[i+1];
if(isInTheRange(i,numberS)) { // 判断是否在范围内10~25
if(i+2==length) { // 这种条件下最右两位为两种情况,所以单独处理
counts[i]+=1;
}else {
counts[i]+=counts[i+2];
}
}
}
}
return counts[0];
}
private boolean isInTheRange(int i, String num) {
String numberS = num.substring(i, i+2);
Integer number = Integer.valueOf(numberS);
return number >= 10 && number <= 25;
}
- 时间复杂度:O(n)。
- 空间复杂度:O(n)。