参考:
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();
}
};