面试题46.把数字翻译成字符串

一、问题描述

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

示例 1:

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”, “mcfi"和"mzi”

提示:

0 <= num < 2 31 2^{31} 231

二、解题思路

方法一:递归回溯

今天的每日一题难度还可以,今天完成的比以往都要早。首先要理解这道题的意思,给定一个数字,可以按位翻译成对应的字母,有多个翻译的意思是例如123这个数字,可以每次取一位翻译成abc,也可以第一次选两位,第二次选一位翻译成lc,也可以第一次取一位,第二次取两位翻译成aw。因此我们可以得到以下结论:

1)每次可以选择一位或两位数字翻译

2)当第一次选择的数字为0时不能再选第二个数字(没有0开头的两位数)

3)当第一次选择的数字>2时不能再选第二个数字(最高到25)

4)当第一次选择的数字为2时,第二次选择的数字不能大于5(最高到25)

因此我们可以像求排列组合那样使用递归回溯法,每次递归都选择一个或两个数字,根据以上的规则建立递归:

1)每次递归都做一个循环,表示取1位或取两位。

2)当取一位时,递归到下一次的循环,重复以上过程直到所有的数字都已经被遍历过,开始回溯。

3)回溯时,中止最后的递归跳回上一层,此时判断这一层递归中第一次取得的数字,如果是0或>2的数字,那么就没有必要再取下一位了,因此直接结束循环回溯到上一层;如果是0或1,就继续取下一位。

4)如果前一位是2且第二位是>5的数字,那么就没有办法翻译成一个字母,因此也要结束循环回溯到上一层。

5)如果第二位也符合要求,那么继续向下一层递归,重复以上过程。

6)直到回溯至第一层执行完毕得到所有的结果。

方法二:取模递归

这个方法是看评论区一位大佬的解法,从给定的数字中每次取出后两位,可以通过模100的方式取得,如果这两位数字<=9或者>=26,说明不能作为一个整体进行翻译,因此假设去掉最后一位,翻译的种类数也不会发生改变,因为最后一位只能单独翻译,所以和原数字/10的结果相同;如果数字在10~26之间说明最后两位可以作为一个整体进行翻译,因此当这两位作为一个整体翻译时,翻译的种类数和原数字/100相同,当最后一位单独翻译时和原数字/10相同,因此这种情况下的翻译种类数为原数字/10+原数字/100.

三、代码

回溯递归:

class Solution {
    private int sum=0;//记录种类数
    public int translateNum(int num) {
        char[] nums=String.valueOf(num).toCharArray();//通过一个char数组进行遍历
        getTranslate(nums,0);
        return sum;
    }

    public void getTranslate(char[] nums,int index){
        if(index==nums.length){//index表示正在遍历数组的下标
            sum++;
            return;
        }
        for(int i=0;i<2&&index<nums.length;i++){
            if(i==0){//取一位
                getTranslate(nums,index+1);
                if(nums[index]=='0'||nums[index]-'0'>2)break;//没有必要取下一位了
                else index++;
            }
            if(i==1){//取两位
                if(nums[index-1]=='2'&&nums[index]-'0'>=6){//这两位>=26
                    break;
                }else{
                    getTranslate(nums,index+1);
                }
            }
        }
    }
}

取模递归:

class Solution {
    public int translateNum(int num) {
        if (num<=9) {return 1;}
        //获取输入数字的余数,然后递归的计算翻译方法
        int ba = num%100;
        //如果大于9或者大于26的时候,余数不能按照2位数字组合,比如56,只能拆分为5和6;反例25,可以拆分为2和5,也可以作为25一个整体进行翻译。
        if (ba<=9||ba>=26) {return translateNum(num/10);}
        else  {return translateNum(num/10)+translateNum(num/100);}
    }
}

四、结果

执行时间0ms100%
消耗内存36.3M100%
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值