题目:给定一个数字,我们按照如下规则把它翻译为字符串:0翻译成"a",1翻译成"b",……,11翻译成"l",……,25翻译成"z"。一个数字可能有多个翻译。例如12258有5种不同的翻译,它们分别是"bccfi"、"bwfi"、"bczi"、"mcfi"和"mzi"。请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。
两种方法:递归和动态规划
用递归自顶向下分析,用动态规划自低向上求解;当最开始的一个或者两个数字被翻译成一个字符后,我们接着翻译后面剩下的数字;用一个递归式来表示:定义f(i)表示从第i位数字开始的不同翻译的数目,那么f(i) = f(i+1) + g(i,i+1)*f(i+2);当第i位和第i+1位两位数字拼接起来的数字在10~25的范围内时,函数g(i,i+1)的值为1,否则为0。该问题使用上面的递归方法会存在很多重复子问题。所以我们使用动态规划的方法,自低向上求解问题,消除重复子问题。
-
int getTranslation(int number)
{
if (number < 0)
return 0;
string numberInString = to_string(number);
//return getTranslationCount(numberInString);
return getTranslationCount(numberInString,0);
}
//动态规划,从后往前
int getTranslationCount(const string &number)
{
int len = number.size();
vector<int> dp(len,0);
int cur = 0;
for (int i = len - 1;i >= 0;--i)
{
if (i < len - 1)
cur = dp[i + 1];
else
cur = 1;
if (i < len - 1)
{
int sum = (number[i] - '0') * 10 + number[i + 1] - '0';
if (sum >= 10 && sum <= 25)
{
if (i < len - 1)
cur += dp[i + 2];
else
++cur;
}
}
dp[i] = cur;
}
return dp[0];
}
//递归,从前往后
int getTranslationCount(const string& number, int i)
{
int len = number.size();
if (i >= len - 1)
return 1;
if (i < len - 1)
{
int sum = (number[i] - '0') * 10 + number[i + 1] - '0';
if (sum >= 10 && sum <= 25)
return getTranslationCount(number, i + 1) + getTranslationCount(number, i + 2);
}
return getTranslationCount(number, i + 1);
}