剑指 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;
    }
}

 

posted @ 2023-02-02 13:53  忧愁的chafry  阅读(11)  评论(0编辑  收藏  举报