ac59把数字翻译成字符串

扣我传送

题目

给定一个数字,我们按照如下规则把它翻译为字符串:

0 翻译成 a,1 翻译成 b,……,11 翻译成 l,……,25翻译成 z

一个数字可能有多个翻译。

例如 12258 有 5 种不同的翻译,它们分别是 bccfibwfibczimcfimzi

请编程实现一个函数用来计算一个数字有多少种不同的翻译方法。

数据范围

输入数字位数 [1,101]。

样例
输入:"12258"

输出:5

代码和思路

看到这个题我的第一反应是递归,那就拿出我的递归三板斧:

  • 假设这个递归你已经写完了,能直接用。
  • 分析问题,看怎么拆分成子问题
  • 找到特殊的结束递归点

思路

递归的函数要干什么?

假设递归写完的前提是你得知道你写的函数是做什么的。对这道题直接就是题目问的东西了:

输入一串数字的字符串,输出他翻译方法的种类数。

这样我们就直接假设我们已经实现这个功能了,我们来具体看看怎么拆分成子问题。

拆分子问题

因为翻译范围是0~25,所以对一个字符串拆分就两种方式:

  1. 把当前字符串的第一个字符翻译为字母,之后再把剩下的字符串递归。
  2. 把当前字符串的前两个字符翻译为字母,之后再把剩下的字符串递归。

第一种情况很简单,0~9都有对应的字母,所以无论开头的是什么数字都可以直接翻译。

复杂的是第二种情况。下面我整理了下:

  • 当前两个字符组成的数字大于25,意味着没有对应的字母能翻译。这时不用对下面的数进行递归,直接为0
  • 当开头的第一个数字为0(01,02…)时,也没有对应的字母能翻译。这时不用对下面的数进行递归,直接为0

这里需要一个把string转换为int的功能,我们写一个函数:

int toInt(string str) {
    int len = str.length(), ans = 0;
    for (int i = 0; i < len; i++) {
        ans *= 10;
        ans += str[i] - '0';
    }
    return ans;
}

之后依据我们总结的条件能写出以下代码:

int getTranslationCount(string s) {
    int first = 0, second = 0;
    first = getTranslationCount(s.substr(1));  // 第一个字符
    
    // 前二个字符
    second = (s[0] == '0' || toInt(s.substr(0, 2)) > 25) ? 0 : getTranslationCount(s.substr(2)); 
    return first + second;
}

结束递归的条件

当这个递归进行到最下的时候大概有3种特殊情况:

  1. 传入递归的字符串长度为0
  2. 传入递归的字符串长度为1
  3. 传入递归的字符串长度为2

第一种情况和第二种情况很简单,字符串长度为0就没得翻译,返回0;字符串长度为1就只有1种翻译方法,返回1。

当第三种情况时,可能翻译的方法有两种,一种翻译成两个字母,一种翻译成一个字母。

if (s.length() == 0) return 0;
if (s.length() == 1) return 1;
if (s.length() == 2) {
    if (S[0] == '0' || toInt(s) > 25) return 1;
    return 2;
}

代码

class Solution {
public:
    int toInt(string str) {
        int len = str.length(), ans = 0;
        for (int i = 0; i < len; i++) {
            ans *= 10;
            ans += str[i] - '0';
        }
        return ans;
    }

    int getTranslationCount(string s) {
        if (s.length() == 0) return 0;
        if (s.length() == 1) return 1;
        if (s.length() == 2) {
            if (s[0] == '0' || toInt(s) > 25) return 1;
            return 2;
        }

        // s长度一定大于2
        int first = 0, second = 0;
        first = getTranslationCount(s.substr(1));
        second = (s[0] == '0' || toInt(s.substr(0, 2)) > 25) ? 0 : getTranslationCount(s.substr(2));
        return first + second;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值