剑指Offer-面试题46:把数字翻译成字符串

这是是题目描述:剑指Offer-面试题46:把数字翻译成字符串

方法一:递归

定义函数f(i)表示以从左向右第i位开始的不同翻译数目,有f(i)=f(i+1)+f(i+2)*g(i,i+1),表示分别以第i位的一位数字和第i:i+1的两位数字为前缀的翻译数目的和就是我们要求的和,g(i,i+1)表示第i:i+1的两位数字是否在10~25的范围内,若是,g(i,i+1)=1,否则g(i,i+1)=0,递归求f(i+1)f(i+2)

题解代码:

class Solution {
    public int translateNum(int num) {
        String str=num+"";
        return translateStr(str);
    }
    int translateStr(String str)
    {
        if(str.length()<=1)
        {
            return 1;
        }
        int sum=0; //统计当前str能被翻译成的字符串的个数
        for(int i=0;i<str.length();i++)
        {
            String preFix=str.substring(0,i+1);
            int preNum=Integer.parseInt(preFix);
            if(preNum>25 || (preFix.length()>1 && preFix.charAt(0)=='0'))
            {
                break;
            }
            sum+=translateStr(str.substring(i+1));
        }
        return sum;
    }
}
方法二:从最小子问题开始分析,消除重叠子问题

递归法是从最大的问题开始,自上而下解决问题,但存在重复的子问题: 以数字12258为例可分解为两个子问题:翻译12258,以及翻译12258。而翻译2258同样可分解为翻译2258以及翻译2258。这里子问题翻译258重复了

因此,我们可以从最小的子问题开始自下而上的解决:以12258为例,先翻译最右边的858并记录下来;再翻译258,可分解为已经记录的子问题858,将它们相加就是258的结果;依次类推得到225812258的结果,且没有重复计算子问题

题解代码:

class Solution {
    public int translateNum(int num) {
        String str=num+"";
        return translateStr(str);
    }
    int translateStr(String str)
    {
        int[] count=new int[str.length()+1]; //count[i]存储str[i:str.lrngth]所对应的数字能翻译成的字母字符串个数
        count[count.length-1]=1; //多加的最后一位方便计算
        count[count.length-2]=1;
        for(int i=count.length-3;i>=0;i--)
        {
            count[i]+=count[i+1];
            if(Integer.parseInt(str.substring(i,i+2))<=25 && str.charAt(i)!='0')
            {
                count[i]+=count[i+2];
            }
        }
        //System.out.println(Arrays.toString(count));
        return count[0];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值