给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法(有很多重复的子问题->动态规划)。

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是”bccfi”, “bwfi”, “bczi”, “mcfi”和”mzi”

动态规划

状态转移方程:不同规模问题之间的关系


image.png

分步计数:每个方法都相互依存,只有各个步骤都完成,才算做完,所以要相乘
分类计数:每个方法都相互独立,所以相加

  1. const translateNum = function (num) {
  2. let numStr = num.toString();
  3. let len = numStr.length;
  4. if (len < 2) return len;
  5. let dp = [1, 1];
  6. for (let i = 2; i <= len; i++) {
  7. let curNum = Number(numStr[i - 2] + numStr[i - 1]);
  8. if (curNum >= 10 && curNum <= 25) {
  9. dp[i] = dp[i - 1] + dp[i - 2];
  10. } else {
  11. dp[i] = dp[i - 1];
  12. }
  13. }
  14. return dp[len];
  15. };

规范一点

  1. const translateNum = (num) => {
  2. const str = num.toString();
  3. const n = str.length;
  4. // 数组初始化大小
  5. const dp = new Array(n + 1);
  6. dp[0] = 1;
  7. dp[1] = 1;
  8. for (let i = 2; i < n + 1; i++) {
  9. // 当前遍历到的两个数字字符
  10. const temp = Number(str[i - 2] + str[i - 1]);
  11. // 两个数字字符组成的数字能直接翻译
  12. // 相当于爬楼梯能爬两格/一格
  13. // 可以两个数字翻译成一个字母,也可以两个数字)
  14. if (temp >= 10 && temp <= 25) {
  15. dp[i] = dp[i - 1] + dp[i - 2];
  16. }
  17. // 不能直接翻译
  18. // 相当于爬楼梯只能爬一格
  19. else {
  20. dp[i] = dp[i - 1];
  21. }
  22. }
  23. return dp[n]; // 翻译前n个数的方法数,即翻译整个数字
  24. }