刷题:把数字翻译成字符串

96 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

题目来源:剑指 Offer 46. 把数字翻译成字符串

题目:

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

示例 1:

输入: 12258

输出: 5

解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"

提示:

0 <= num < 2^31

思路分析:

动态规划:

状态表示:dp[i]表示前i个数字有多少种翻译方法,则dp[n]便表示前n个数字有多少中翻译方法,即结果。

状态转移:

  • 当把第i个数字单独翻译成一个字符时,相当于第i个数字已经固定翻译成什么了,则整个数字串有dp[i - 1]种翻译方法
  • 当把第i - 2和第i-1个数字合在一起翻译成一个字符时,则整个数字串有dp[i - 2]种翻译方法,但此时应满足第i - 2和第i-1个数字合在一起能翻译成一个字符,即他们两个组成的数字在[10,25]范围内才行。

转移方程:

dp[i]={dp[i1]+dp[i2]xi1+xi2[10,25]dp[i1]elsedp[i]=\begin{cases} dp[i−1]+dp[i−2] & xi-1+xi-2∈[10,25]\\ dp[i−1] & else \end{cases}

时间复杂度:

循环的次数是 n 的位数,故渐进时间复杂度为 O(logn)。

空间复杂度:

虽然这里用了滚动数组,动态规划部分的空间代价是 O(1) 的,但是这里用了一个临时变量把数字转化成了字符串,故渐进空间复杂度也是O(logn)。

AC代码:

class Solution {
public:
    int getTranslationCount(string s) {
        string str=to_string(num);
        if(s.empty()) return 0;
        int len = s.size();
        int dp[len+1];
        memset(dp,0,sizeof(dp));
        dp[0] = 1;
        dp[1] = 1;
        for (int i=2;i<=len;i++){
            dp[i] = dp[i-1];
            int  k = s[i-1] - '0';
            int k1 = s[i-2] - '0';
            if (k1 * 10 + k <= 25 && k1 != 0){
                dp[i]  += dp[i-2];
            }
        }
        return dp[len];
    }
};

结果

image.png