一、题目
题目链接:力扣
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 2^31
二、题解
1、思路
🎃 动态规划
本题类似于,青蛙跳台阶有多少种跳法。
动态规划四大步骤:
穷举分析
对于12258:
1→b;1种;
12→bc,m;2种;
122→bcc,mc,bw;3种;
1225→bccf,mcf,bwf,mz,bcz;5种;
12258→bccfi,mcfi,bwfi,mzi,bczi;5种;
分析找规律,拆分子问题
我们先定义dp[i]为一个有i位的数字能够翻译成字符的个数。
通过穷举分析,我们发现:“1225”就是在“122"基础上加f,有3种;并且刚好5,也就是f,能够和122的末尾的2形成翻译,把2和5组成25后,能够组成“12”能够翻译成的字符个数,有2种;那么”1225“共有5种。
对于”12258“,我们发现在”1225“的基础上加i,有5种;但是末尾的8和前面”1225“的5无法组成翻译,有0种;因此”12258“共5种。
最简单的边界情况
dp[1] = 1;也就是只有一位数字,只有一种情况。
状态转移方程
当前num后面两位能够组成翻译:dp[i] = dp[i-1] + dp[i-2];
当前num后面两位不能组成翻译:dp[i] = dp[i-1];
现在看来完全类似青蛙跳台阶!
2、代码实现
🎃 动态规划
注意一点:“09”和“9”不一样!“09”无法翻译成一个字符。
好理解的
class Solution {
public:
int translateNum(int num) {
int last_last_dp = 1;// dp[i-2],初始化为dp[0]=1
int last_dp = 1;// dp[i-1],初始化为dp[1]=1
int dp = 1;// num只有一位,不进循环
string str = to_string(num);
for(int i = 2; i <= str.size(); i++)
{
string temp = str.substr(i-2, 2);
if(temp > "25" || temp < "10")
{
dp = last_dp;
}
else
{
dp = last_dp + last_last_dp;// 要启动循环,必须使last_last_dp初始化为1。比如num等于25时进入此处,last_dp等于1(即dp[1]),此时的最后两个字符即25,在范围内,需要求dp[i-1]=dp[0],等于多少呢?前面没有字符,不变,只有25一种可能,所以是1
}
last_last_dp = last_dp;
last_dp = dp;
}
return dp;
}
};
自己写的
class Solution {
public:
int translateNum(int num) {
int last_last_dp = 1;// dp[i-2]
int last_dp = 1;// dp[i-1]
int dp = 1;// dp[i]初始化为dp[1]
string str = to_string(num);
for(int i = 2; i <= str.size(); i++)
{
if(str[i-1-1]=='1' || (str[i-1-1]=='2' && str[i-1]<'6'))
{
dp = last_dp + last_last_dp;
}
else
{
dp = last_dp;
}
last_last_dp = last_dp;
last_dp = dp;
}
return dp;
}
};
3、复杂度分析
🎃 动态规划
时间复杂度:循环的次数是 n 的位数,故渐进时间复杂度为 O(logn)。
空间复杂度:这里用了一个临时变量把数字转化成了字符串,故渐进空间复杂度也是 O(logn)。
4、运行结果
🎃 动态规划
好理解
自己写的