剑指offer46:把数字翻译成字符串

来审一下题,num最大的范围在int内。这个数字emmm,反正不大记得,总之位数也不多好像。

额,那么我们如何分析这道题呢,以下是分析的过程:

就对题目中的12258来分析,如果给你这道题,你会怎么做?

如果是我,我会先拿出1变成b,后面2258再另作分析,当然,由于a-z是对应的0-25,所以我们还能先把12(10\leq 12\leq25)拿出来,然后258再另作分析。啊哈,这样,dp的转移方程就有了不是么,应该长下面这样:

f(i)=\begin{cases} & \text 1,i=0 \\ & \text f(i-1)+cf(i-2),i\geq 1 \end{cases}

c当且仅当当前的第i位与第i-1位形成的数字大于等于10且小于等于25时取1,否则取0,emmm,是不是说清楚了?

那我们可以开始写代码了,当然,这种是可以用滚动数组节省空间复杂度的,可以看看《剑指offer》42连续子数组的最大和:剑指offer42:连续子数组的最大和_lsgoose的博客-CSDN博客来看看用数组和用几个变量的区别,然后,这里写上用滚动数组的代码:

class Solution {
public:
    int translateNum(int num) {
        string src=to_string(num);
        auto len=src.size();
        //p记录f(i-1)
        //q记录f(i-2)
        //这里r初始化为1  表示第一个数字单独拿出来的情况
        int p,q=0,r=1;
        for(int i=0;i<len;++i)
        {
            p=q;
            q=r;
            r=0;
            r+=q;
            if(i==0)
            {
                continue;
            }
            auto pre=src.substr(i-1,2);
            if(pre<="25"&&pre>="10")
            {
                r+=p;
            }
        }
        return r;
    }
};

结果如下所示:

 当然,有自底向上的,也会有自顶向下的递归写法:

class Solution {
public:
    int translateNum(int num) {
        if(num<10)
        {
            return 1;
        }
        if(num%100>=10&&num%100<=25)
        {
            return translateNum(num/10)+translateNum(num/100);
        }
        return translateNum(num/10);
    }
};

 这里的细节:

用除法代替i-1和i-2操作,用%100完成对末尾两位数的提取

结果如下所示:

为什么递归的内存消耗还小一些,有无懂哥解释以下......

总结一下:dp的题目关键在于判断是否是dp,或者说是要能自顶向下找出规律写出转移方程,然后还能自底向上或者自顶向下写出代码,有时候用滚动数组可以优化空间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值