面试题:把数字翻译成字符串
题目:
给定一个数字,我们按照如下规则把它翻译为字符串:
0——“a”;1——“b”;……;11——“l”;25——“z”
一个数字可能有多个翻译
如12258有5种不同的翻译,分别是“bccfi”、“bwfi”、“bczi”、“mcfi”、“mzi”
请实现一个函数,用来计算一个数字有多少种不同的翻译方法
思路:
最开始的思路,从左到右,如12258,先从12开始,12<25,所以可分为两个部分来递归进行,但是缺点是【有太多重复运算】,具体可以动手写一下,如258需要计算多次
所以采用的自底向上的方法,消除了重复的问题
用例子来解释一下
eg:12258
算法中设置了两个count,设当前计算种数的位置为从右到左数第x位,则count1为第x-1的种数,count2为第x-2的种数
初始的count1=count2=1,
当【x位和x-1位】的数组合起来>25时,count2替换为count1的值,count1=1
当【x位和x-1位】的数组合起来<25时,count1等于count1+count2,count2替换为count1之前的值(也就是没有加法计算之前的值,此处用一个temp变量来实现)
最后返回count1
——为什么要这么做,看下面的解释——
从12258的最右开始找寻规律
1)最右边是8,只有一个数字,所以只有【1种】翻译方式
count1=1 count2=1(初始化的值)
2)再往右边是5,此时58>25,所以也只有【1种】翻译方式,即5、8分别翻译——也就是count1依旧是1
count1=1 count2=1 (count1记录的是【58】的翻译种数,count2记录的是【8】的翻译种数)
3)再往右边是2,此时25=25,因此25可拆成2+58与25+8
由于在单个的情况中,2或25是已经固定的,所以2+58的情况中,翻译方式种数等于58的翻译方式种数;25+8的翻译方式种数等于8的翻译方式种数——所以此时种数为8+58的种数,即1)和2)中的种数——也就是count1+count2=2(25 8 / 2 5 8)
count1=2 count2=1 (count1记录的是【258】的翻译种数,count2记录的是【58】的翻译种数)
4)再往右是2,此时22<25,因此可拆成2+258和22+58,同3)中,2+258为2,22+58为1,所以此时count1=2+1=3,count2=2
count1=3 count2=2 (count1记录的是【2258】的翻译种数,count2记录的是【258】的翻译种数)
5)再往右是1,此时12<25,因此可拆成1+2258和12+258,1+2258为3,12+258为2,此时count1=5,count2=3
count1=5 count2=3 (count1记录的是【12258】的翻译种数,count2记录的是【2258】的翻译种数)
【代码】
public class Q46 {
public static void main(String[] args) {
int x = 11126;
System.out.println(howmanyString(x));
}
public static int howmanyString(int a) {
int count1 = 1;
int count2 = 1;
while(a/10!=0) {
if(a%100>25) {
count2 = count1;
count1 = 1;
}else {
int temp = count1 + count2;
count2 = count1;
count1 = temp;
}
a = a/10;
}
return count1;
}
}