每日一题-70. 爬楼梯、面试题46. 把数字翻译成字符串

每日一题-70. 爬楼梯、面试题46. 把数字翻译成字符串

  • 题目1描述
  • 题目1分析
  • 解决1方案
  • 题目2描述
  • 题目2分析
  • 解决2方案

这星期在leetcode上刷题中遇到了两道很类似的题,一道题难度简单,一道题难度中等,其本质上可以用同一种解法,在这里分享一下。

题目1描述

70. 爬楼梯
难度:简单
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
示例 2:
输入: 3
输出: 3
通过次数220,456提交次数443,697
来源:力扣(LeetCode)

题目1分析

爬楼梯这算是一个老问题了,本质上就是求解斐波那契数列数列。斐波那契数列是什么这里不多解释,就是前两项之和等于后一项。关于斐波那契数列性质的研究在国际上也有许多论文,暂且不谈。在leetcode的官方题解十分花哨,弄出了动态规划,矩阵快速幂,通项公式三种解法。在这里简单的用动态规划来求解。

解决1方案

斐波那契数列的递推方程 f(n) = f(n - 1) + f(n - 2)f(n)=f(n−1)+f(n−2)。
配合滚动数组的思想获得以下代码。

class Solution {
public:
    int climbStairs(int n) {
        if(n==0)return 0;
        if(n==1)return 1;
        if(n==2)return 2;
        int a=1;
        int b=2;
        int ans=0;
        for(int index=3;index<=n;++index)
        {
            ans=a+b;
            a=b;
            b=ans;
        }
        return ans;
    }
};

时间复杂度为O(n),空间复杂度为O(1)。接下来,我们看看第二道题。

题目2描述

面试题46. 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”, “mcfi"和"mzi”
提示:
0 <= num < 231
通过次数29,704提交次数54,719

题目2分析

这道题比之前的爬楼梯更进了一步,从无限制的爬楼梯变成了有限制的爬楼梯。我把这道题套入爬楼梯的题目中,那便是:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每一阶楼梯都有一个随机数,为[0-9]。
你可以爬 1 个台阶。当接下来两个台阶组成的数字是[10-25]时,你可以爬1个或2个台阶。你有多少种不同的方法可以爬到楼顶呢?

假设,楼梯的编号全是[1-2],那么这道题的答案与无限制的爬楼梯答案一致。但是若其中出现了无法组成指定数字的情况那么该台阶只有爬一个台阶这一个选项,对于答案不构成影响。因此楼梯被分割为一片片由指定数字组成的子楼梯。子楼梯的走法相互独立,答案为各个子楼梯走法之积。
leetcode给出的官方解法是动态规划,但是写得不太好理解。在这里,我采用爬楼梯的解答简化题解。

解决2方案

class Solution {
public:
    int translateNum(int num) {
        stringstream ss;
        string str;
        ss<<num;
        ss>>str;
        int count=1;
        int sublen=0;
        bool isc=false;
        char c;
        for(int index=0;index<str.size();++index)
        {
            c=str.at(index);
            switch(c)
            {
            case '1':
                sublen+=1;
                isc=false;
                break;
            case '2':
                sublen+=1;
                isc=true;
                break;
            case '0':
            case '3':
            case '4':
            case '5':
                if(sublen<=0)
                {
                    continue;
                }
                sublen+=1;
                count*=fbnq(sublen);
                sublen=0;
                break;
            default:
                if(sublen<=0)
                {
                    continue;
                }
                if(!isc)
                {
                    sublen+=1;
                }
                count*=fbnq(sublen);
                sublen=0;
                
            }
        }
        if(sublen>0)
        {
            count*=fbnq(sublen);
        }
        return count;
    }

    int fbnq(int n){
        if(n==0)return 0;
        if(n==1)return 1;
        if(n==2)return 2;
        int a=1;
        int b=2;
        int ans=0;
        for(int index=3;index<=n;++index)
        {
            ans=a+b;
            a=b;
            b=ans;
        }
        return ans;
    }
};

有没有觉得fbnq这个函数的代码有点眼熟?没错,其就是之前爬楼梯的代码。主函数判断无限制的子楼梯长度,fbnq这个函数则计算子楼梯的走法数,最后主函数将各个子楼梯的走法数相乘,便是该题的答案。

你可能感兴趣的:(每日一题,经典问题)