剑指 Offer 46. 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258 输出: 5 解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 231
思路
有点像青蛙跳台阶的题目,每次向前前进一格,或者向前前进两格,最后中跳上n个台阶的一共的方式种数有dp[n] = dp[n-1]+dp[n-2]
一次跳2格是有条件的,就是前后两各数字组成的2位数必须在[10, 25]之间
所以状态转移方程为dp = dp[n-1] 当XnXn-1不在[10, 25]区间时
dp = dp[n-1] + dp[n-2], 当XnXn-1在[10, 25]区间时
1 class Solution { 2 public int translateNum(int num) { 3 4 // 为方便索引,把num转换成字符串 5 String str = String.valueOf(num); 6 int len = str.length(); 7 int[] dp = new int[len+1]; 8 9 dp[0] = 1; 10 dp[1] = 1; 11 for(int i = 2; i <= len; i++){ 12 String tmp = str.substring(i-2, i); 13 if(tmp.compareTo("10") >= 0 && tmp.compareTo("25") <= 0){ 14 dp[i] = dp[i-1] + dp[i-2]; 15 }else{ 16 dp[i] = dp[i-1]; 17 } 18 } 19 return dp[len]; 20 } 21 }
leetcode执行用时:0 ms > 100.00%, 内存消耗:35.8 MB > 8.40%
复杂度分析:
时间复杂度:把数字num的每一位都遍历了一遍,所以时间复杂度为O(n)
空间复杂度:把数字转换成了字符串,需要一个O(n)的空间,另外还需要一个dp数组,所以一共需要O(2n)的空间
改进-空间优化
发现其实每个dp[i]只和dp[i-1] 和 dp[i-2]有关,所以只需要两个局部变量不断迭代即可,可以省去dp数组的空间复杂度
1 class Solution { 2 public int translateNum(int num) { 3 4 // 为方便索引,把num转换成字符串 5 String str = String.valueOf(num); 6 int len = str.length(); 7 // int[] dp = new int[len+1]; 8 9 int a = 1; 10 int b = 1; 11 int res = 0; 12 for(int i = 2; i <= len; i++){ 13 String tmp = str.substring(i-2, i); 14 if(tmp.compareTo("10") >= 0 && tmp.compareTo("25") <= 0){ 15 res = a + b; 16 }else{ 17 res = a; 18 } 19 b = a; 20 a = res; 21 } 22 return a; 23 } 24 }
leetcode执行用时:0 ms > 100.00%, 内存消耗:35.6 MB > 55.83%
复杂度分析:
时间复杂度:把数字num的每一位都遍历了一遍,所以时间复杂度为O(n)
空间复杂度:把数字转换成了字符串,需要一个O(n)的空间,所以一共需要O(n)的空间