剑指 Offer 46. 把数字翻译成字符串
题目:
思路:
【1】其实这道题相当于跳台阶的变种,其变化在于有限制的情况下是只允许跳一格,本质上还是可以用公式 F(N) = F(N-1) + F(N-2)
【2】采用递归的话,画一颗树出来可能会更加直观一些。
代码展示:
基于递归的处理方式:
//时间0 ms击败100% //内存38.7 MB击败6.93% class Solution { public int translateNum(int num) { if (num == 0){ return 1; } return dfsTranslateNum(num); } public int dfsTranslateNum(int num) { if (num < 10){ return 1; } if (num % 100 < 26 && num % 100 > 9) { return dfsTranslateNum(num / 10) + dfsTranslateNum(num / 100); } else { return dfsTranslateNum(num / 10); } } }
既然已经出现了基于递归的方式,那么必然可以转成基于循环的方式:
//时间0 ms击败100% //内存38.6 MB击败13.40% class Solution { public int translateNum(int num) { char[] ch = String.valueOf(num).toCharArray(); int len = ch.length; int[] dp = new int[len + 1]; dp[0] = 1; dp[1] = 1; for(int i = 2; i <= len; i++){ int n = (ch[i - 2] - '0') * 10 + (ch[i - 1] - '0'); if(n >= 10 && n <= 25){ dp[i] = dp[i - 1] + dp[i - 2]; }else{ dp[i] = dp[i - 1]; } } return dp[len]; } } //时间0 ms击败100% //内存38.4 MB击败39.77% //基于上面动态规划我们会发现其实也是采用了公式,而且只需要两个变量,进行推导,那么是不是可以减少一下额外的空间开销,起到优化效果 class Solution { public int translateNum(int num) { String str = String.valueOf(num); //初始化p为dp[-1] =0,q为dp[0]=1,res=1 int p=0,q=1,res=1; for(int i =1 ; i<str.length();i++){ //dp[i]从i-1过来 p=q;//p从上一轮i-2(真实的i-3)变为这一轮的i-2 q=res;//res为上一轮的i赋值到q即q为这一轮的i-1 res=q;//本轮i从i-1拿数据,这里可能会跟上一行搞迷,想清楚,res每次循环完都是当前最新的。 String sub = str.substring(i-1,i+1);//i+1不包含 //dp[i]从i-2过来 if(sub.compareTo("25") <= 0 && sub.compareTo("10" ) >= 0 ){//ascii码进行比较,sub-“25” res+=p; } } return res; } }