题目地址:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/
题目描述
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
题目示例
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
解题思路
对于一个数,我们要分两种情况进行翻译,第一,只翻译自己本身;第二,与前面的数字组合翻译,其值要小于25,否则,翻译的次数和前面数字翻译的次数一样多。类似于爬楼梯那道题。
动态规划:此问题可以看作每次选择一个数字或两个数字用来合并成一个字符,求可以合成多少种字符串。dp[i]表示前i个字符的翻译数,对i取一个字符时,则一定在0只25内,此时dp[i] = dp[i-1],表示从i-1到i的路径;当对i取两个字符时,只有在0~25以内时,才有dp[i] = dp[i-2],表示从i-2到i的路径;状态转移方程为当num[i]和num[i-1]能合成一个字符时,dp[i]=dp[i-1],否则,dp[i]=dp[i-1]+dp[i-2]
递归:首先确定一个前缀,前缀有两种可能,单个数或者两位数,两位数限与10到25,我们从低位开始(个位和十位),得到数字的两个前缀,一位数前缀直接递归计算,只有在[10,25]范围内的两位数才能作为前缀递归计算。最后,累计两种前缀的所有方法。
程序源码
动态规划
class Solution { public: int translateNum(int num) { if(num == 0) return 1; string s = to_string(num); vector<int> dp(s.size() + 1); dp[0] = 1; dp[1] = 1; for(int i = 1; i < s.size(); i++) { if(s[i - 1] == '0' || s.substr(i - 1, 2) > "25") dp[i + 1] = dp[i]; else dp[i + 1] = dp[i] + dp[i - 1]; } return dp[s.size()]; } };
递归
class Solution { public: int translateNum(int num) { if(num <= 9) return 1; //递归出口 int last_two = num % 100; if(last_two <= 9 || last_two >= 26) { return translateNum(num / 10); } else { return translateNum(num / 10) + translateNum(num / 100); } } };
参考文章: