面试题46 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”, “mcfi"和"mzi”
提示:
0
≤
n
u
m
<
2
31
0 \leq num < 2^{31}
0≤num<231
自己对于DP还是不够熟练,这道题目没有很难,但是想了一个多小时。
推一下样例就知道DP的思路了。
以样例来说明:
输入1
1
输入2 2
1 2 -> 1 2 2 / 1 22
12 -> 12 2
输入5 8
1 2 2 -> 1 2 2 5 / 1 2 25 -> 1 2 2 5 8 / 1 2 25 8
1 22 -> 1 22 5 -> 1 22 5 8
12 2 -> 12 2 5/ 12 25 -> 12 2 5 8 / 12 25 8
可以发现以第 i 个数结尾的方案里,i 单独翻译成一个字符是一定可行的,但是 i 是否能够和前一个数一起构造成一个字符,取决于二者的值是否
≤
25
\leq 25
≤25。
但是对i-1结尾的方案来说,比如说输入
1
、
2
、
2
1、2、2
1、2、2,存在
1
、
2
、
2
1、2 、2
1、2、2和
1
、
22
1 、22
1、22两种答案,这个时候再输入5,5是不能追加到22后面的(因为变成了225),因此对于 i 结尾的所有方案,我们要区分以 i 单独结尾的和以
i
−
1
,
i
i-1,i
i−1,i 协同结尾的方案,只有前者能够和
i
+
1
i+1
i+1 构成一个新的字符,后者不可以。
class Solution {
public:
int dp[32][2];
int translateNum(int num) {
string nums = to_string(num);
dp[0][0] = 1;
int n = nums.size();
for(int i=1; i<n; i++) {
dp[i][0] += dp[i-1][0]; //第 i 个数字单独作为一个字符
dp[i][0] += dp[i-1][1];
int sum = (nums[i-1]-'0')*10 + nums[i]-'0';
if( sum>=10 && sum<=25 )
dp[i][1] += dp[i-1][0];
}
return dp[n-1][0]+dp[n-1][1];
}
};