把数字翻译成字符串(动态规划)

参考:
https://www.jianshu.com/p/80e1841909b7

题目要求:
给定一个数字,按照如下规则翻译成字符串:0翻译成“a”,1翻译成“b”…25翻译成“z”。一个数字有多种翻译可能,例如12258一共有5种,分别是bccfi,bwfi,bczi,mcfi,mzi。实现一个函数,用来计算一个数字有多少种不同的翻译方法。

递推公式:
f(i) = f(i+1)+ g(i,i+1)*f(i+2) , g(i,i+1)={0,1} (1)
f(i)表示 从第 i 位开始翻译方法的个数
从这就可以看出和青蛙跳类似,一次跳1个台阶,或者两个(两个的时候要用条件判断下)

书中说的,从前往后算,会有重复计算,所以从后往前算(自下而上)(但公式(1)的计算仍然是从前往后)

#include<iostream>
#include<sstream>
#include<string>
using namespace  std;

int get_ans_string(string s)
{
    int f2 = 1,f1 = 1, g = 0; // f2代表跳1次,剩余的情况;f1代表跳两次剩余的情况;
                            // 每次更新的时候,当前计算出的 总的情况数,为下一次的f2;
                            // 当前的 f2 ,为下一次 的 f1;
		
//	cout<<"s.size(): "<<s.size()<<endl;
	
    for (int i=s.size()-2;i>=0;i--)
    {
        string tmps = s.substr(i,2);
        int tmpint;
        stringstream ss;
        ss<<tmps;
        ss>>tmpint;
        
        if (tmpint>=10 && tmpint<=25)g = 1;
        int tmpf= f2;
        f2 = f2 + g*f1;
        f1 = tmpf;
    }

    return f2;

}

int get_ans_num(int n)
{
    if (n<0)return 0;

    return get_ans_string(to_string(n));

}

int main()
{
    int n;
    cin>>n;

    int ans = get_ans_num(n);
    // cout<<n<<endl;
    cout<<ans<<endl;

    getchar();

    return 0;
}


leetcode上的一道题,注意0不能被编码
由于逆向考虑有点绕,就还从前往后考虑吧
https://leetcode.com/problems/decode-ways/submissions/
https://www.cnblogs.com/grandyang/p/4313384.html
https://zhuanlan.zhihu.com/p/60238439

注意申请dp的时候,多申请一个数。
dp数组的最开始的数相等于一个““辅助”数,其值为1,
dp[i]表示前i个数,能编码的个数;
如果当前数s[i-1]为0 , 则当前数必不能拆分,由此dp[i] = 0; 否则,可以拆分,因此dp[i] = dp[i-1]
然后再判断当前数能否和前一个数组合,如果可以,那么dp[i-2]的组合情况可以和当前组合和并,即可以加上dp[i-2]

class Solution {
public:
    int numDecodings(string s) {
        
        if (s.empty()||s[0]=='0')return 0;
        
        vector<int>dp(s.size()+1,0);
        
        dp[0] = 1;
        
        for (int i=1;i<=s.size();i++)
        {
            if (s[i-1]=='0')dp[i]=0;
            else if (s[i-1]!='0')dp[i] = dp[i-1];
            
            if (i>=2 && (s[i-2]=='1' || (s[i-2]=='2' && s[i-1]<='6'))) dp[i] += dp[i-2];
            
        }
        
        return dp.back();
        
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值