题目描述
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”,
“mcfi"和"mzi”
提示:
0 <= num < 2^31
方法一(递归)
1.解题思路
- 递归终止条件:num只有1位的时候
- 从上一层递归获取什么:当num最后两位组成的数在10到25之间时,当前层为前两层之和;当num最后两位组成的数不在10到25之间时,当前层等于前一层。
- 每一层返回什么:返回当前层的方案数
有点类似“爬楼梯”这道题。
2.代码实现
class Solution {
public int translateNum(int num) {
if(num>=0&&num<=9) return 1;
int mod=num%100;
if(mod>=10&&mod<=25){
return translateNum(num/10)+translateNum(num/100);
}
else{
return translateNum(num/10);
}
}
}
3.复杂度分析
- 时间复杂度:假设n为数字总共有多少位,则时间复杂度为O(n)。
- 空间复杂度:递归栈的深度为数字的位数,所以空间复杂度为O(n)。
方法二(动态规划)
1.解题思路
思路与递归一模一样,不过采用空间换时间的思路,将之前的状态记录下来。实现上可以先把数字转化为字符串,然后再进行遍历。
2.代码实现
class Solution {
public int translateNum(int num) {
String s=String.valueOf(num);
int n=s.length();
int[] dp=new int[n+1];
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++){
int tmp=Integer.parseInt(s.substring(i-2,i));
if(tmp>=10&&tmp<=25){
dp[i]=dp[i-1]+dp[i-2];
}
else{
dp[i]=dp[i-1];
}
}
return dp[n];
}
}
3.复杂度分析
- 时间复杂度:假设n为数字总共有多少位,则时间复杂度为O(n)。
- 空间复杂度:需要长度为n+1的dp数组以及长度为n的字符串,所以空间复杂度为O(n)。
方法三(空间优化)
1.解题思路
可以用两个变量来存储前两层的状态,根据当前余数来跟新当前层与前两层的状态,每次循环将数字最末尾的数抹去。
2.代码实现
class Solution {
public int translateNum(int num) {
int a=1,b=1,c=1;
while(num>0){
int mod=num%100;
if(mod>=10&&mod<=25){
c=a+b;
}
else{
c=b;
}
a=b;
b=c;
num/=10;
}
return c;
}
}
3.复杂度分析
- 时间复杂度:假设n为数字总共有多少位,则时间复杂度为O(n)。
- 空间复杂度:需要额外常数级别的内存空间,所以空间复杂度为O(1)。
剑指offer全集入口: 请戳这里