面试题46: 把数字翻译成字符串(C++)

题目地址: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);
        }
    }
};

参考文章:

https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/solution/dong-tai-gui-hua-dp-by-z1m/

https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/solution/di-gui-qiu-jie-shuang-bai-by-xiang-shang-de-gua-ni/

----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12819593.html