本文参考自《剑指offer》一书,代码采用Java语言。html
更多:《剑指Offer》Java实现合集 java
题目
给定一个数字,咱们按照以下规则把它翻译为字符串:0翻译成"a",1翻译成"b",……,11翻译成"l",……,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),这就是最终要求的结果。测试
测试算例 url
1.功能测试(1个数字;多个数字)spa
2.特殊测试(负数,0,含2五、26等).net
Java代码
//题目:给定一个数字,咱们按照以下规则把它翻译为字符串:0翻译成"a",1翻 //译成"b",……,11翻译成"l",……,25翻译成"z"。一个数字可能有多个翻译。例 //如12258有5种不一样的翻译,它们分别是"bccfi"、"bwfi"、"bczi"、"mcfi"和 //"mzi"。请编程实现一个函数用来计算一个数字有多少种不一样的翻译方法。 public class TranslateNumbersToStrings { public int getTranslationCount(int number) { if(number<0) return 0; String sNumber=String.valueOf(number); int len=sNumber.length(); int[] counts=new int[len]; for(int i=len-1;i>=0;i--) { if(i==len-1) { counts[i]=1; }else { counts[i]=counts[i+1]; if(canBeTrans(sNumber,i)) { if(i==len-2) counts[i]+=1; else counts[i]+=counts[i+2]; } } } return counts[0]; } private boolean canBeTrans(String sNumber, int i) { int a=sNumber.charAt(i)-'0'; int b=sNumber.charAt(i+1)-'0'; int convert=a*10+b; if(convert>=10 && convert<=25) return true; return false; } public static void main(String[] args) { TranslateNumbersToStrings demo= new TranslateNumbersToStrings(); System.out.println(demo.getTranslationCount(0)==1); System.out.println(demo.getTranslationCount(10)==2); System.out.println(demo.getTranslationCount(12258)==5); System.out.println(demo.getTranslationCount(-100)==0); } }
收获
1.递归方法,咱们试着用公式描述会比较清晰翻译
2.递归是自上而下解决问题,若是遇到重复的子问题时,考虑自下而上求解,不用递归code
3.g(i,i+1)不只要判断<=25,还要判断>=10,别漏了