一开始我的想法是从后面向前面不断对100取余,如果这个余数大于等于10并且小于等于25,说明这两位既可以做一个大的字母,也可以做两个小的字母。所以对于前面的n-2个数字来说,后面的连个数字使得前面的n-2个数字的结果数翻了一倍,所以我定义count=1,不断对100取余,只要符合条件就count就乘以2,num除以100去掉后面两位再循环,提交的时候一个220的用例就没过,我意识到了错误,我的算法把数字全分成2位2位的,它还可以分成2位1位2位这样的,然后又试了用递归,再主方法里面先去掉最后一位递归,如果符条件,再去掉后两位递归,每次递归cout++,但是这样是有问题的这样统计的不是结果数而是不完整字母数,然后就看题解了,看到f(i)=f(i-1)+f(i-2)就恍然大悟了,立马自己去写了代码,一遍ac,代码如下:
class Solution {
public int translateNum(int num) {
int num1 = num;
int count =1;
while(true){
if(num1 / 10 == 0){
break;
}else{
num1 = num1 / 10;
count++;
}
}
return translate(count, num);
}
public int translate(int index, int num){
if(num < 10)return 1;
if(num % 100 >= 10 && num % 100 <= 25 ){
return translate(index-1, num / 10) + translate(index-2, num / 100);
}else{
return translate(index-1, num / 10);
}
}
}
定义f(i)表示以第i位结尾的方案数,如果后面两位符合>=10并且<= 25,那么f(i)=f(i-1)+f(i-2),否则f(i)=f(i-1)。最后剩一个“个位”(首位)就返回1。可以想象为有很多条路径通向最后一个”个位“,把所有路径加起来就是方案的总数。(通向最后一个两位数的路径也加进去了,因为这个两位数也分成了两个一位数加进去了),或者可以想象成这个数字有多少种拆分方案,1211还是122.......每一种方案都加了1。写完后我又看了一下题解代码,和我的还不太一样。
class Solution {
public int translateNum(int num) {
String src = String.valueOf(num);
int p = 0, q = 0, r = 1;
for (int i = 0; i < src.length(); ++i) {
p = q;
q = r;
r = 0;
r += q;
if (i == 0) {
continue;
}
String pre = src.substring(i - 1, i + 1);
if (pre.compareTo("25") <= 0 && pre.compareTo("10") >= 0) {
r += p;
}
}
return r;
}
}
它先把数字转换成了字符串,利用滚动数组实现,把数组压缩成3个变量,具体的算法思想,目前还没看懂,现在需要去开会,稍后再看。