面试题46.把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi”, “bwfi”, “bczi”, “mcfi"和"mzi”
提示:
0 <= num < 231
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
思路一:
动态计划
- 动态规划三步走
- 定义状态
- dp[i] 表示 截止第 i 位, 把数字翻译成字符串的个数
- 定义初始值
- dp[0] = 1, dp[1] = 1; 0 或者 1位时,只有一个可能性
- 状态转移方程
- 计算第 i 位, 即 dp[i] 时
- 有两种情况,dp[i] = dp[i - 1]
- 如果第 i-1位为0,说明 i-1位 和 第 i 位 合并,仍然是 i。
- 如果 i-1位 > 2 或者 i-1位==2,且i位 > 5. i-1和i合并后的无相应字母表示
- 除开上述两种情况,则dp[i] =dp[i - 1] + dp[i - 2]
- dp[i - 1] 代表 i 与 i-1不合并的情况
- dp[i - 2] 代表 i 与 i - 1 合并的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/**
*
* 动态规划
* 当 num < 10时,只有一个结果
*
* 三个步骤
* 定义状态
* dp[i] 表示截止 i 位,把数字翻译成字符串的 个数
* 定义初始值
* dp[0] = 1, dp[1] = 1. 0 或者 1时,只有一个可能
* 状态转移方程
* 计算第 i 位,即dp[i] 时
* 如果 第 i-1位为0,说明 i-1位和第i位合并,仍然是i。
* 如果 i-1位 + i位 > 25,则没有字母来表示 合并的数组了
* 所以这两种情况, dp[i] = dp[i - 1]
*
* 除开这两种情况
* 则 dp[i] = dp[i-1] + dp[i-2]; 也就是所有 i-1和i合并的值 和 i-1和i不合并当前情况
*
* */
public int translateNum1(int num) {
if (num < 10) return 1;
String string = String.valueOf(num);
int count = string.length();
int[] dp = new int[count + 1];
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= count; i++) {
char pre = string.charAt(i - 2);
char cur = string.charAt(i - 1);
if (pre == '0' || pre > '2' || (pre == '2' && cur > '5')){
dp[i] = dp[i - 1];
}else {
dp[i] = dp[i - 1] + dp[i - 2];
}
}
return dp[count];
}
|
复杂度分析:
- 时间复杂度 : O(N)
- 空间复杂度 : O(N)
思路二:
上述解题过程中,我们发现,在递推dp[i] 时,我们只用到了 dp[i - 1] 和 dp[i - 2], 所以我们可以将时间复杂度优化至 O(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/**
*
* 空间复杂度的优化
* 上边题解中,我们使用了额外的dp数组存储空间
* 但是,我们在递推计算dp[i]的过程,只用到了 dp[i-1] 和 dp[i-2]
* 所以,我们可以将空间复杂度由原来的 O(N) 优化至 O(1)
*
* */
public int translatNum2(int num){
if (num < 10) return 1;
String string = String.valueOf(num);
int count = string.length();
int a = 1, b = 1;
for (int i = 2; i <= count; i++) {
char pre = string.charAt(i - 2);
char cur = string.charAt(i - 1);
if (pre == '0' || pre > '2' ||(pre == '2' && cur > '5')){
a = b;
}else {
int tmp = b;
b += a;
a = tmp;
}
}
return b;
}
|
复杂度分析 :
时间复杂度 : O(N)
空间复杂度 : O(1)