zoukankan      html  css  js  c++  java
  • Leetcode---剑指Offer题10---斐波那契数列




    剑指Offer-面试题9---斐波那契数列

    1、题目1:输出斐波那契数列

    https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/
    输入n,输出斐波那契数列位于第n位的值。

    递归的方式效率会很低,因为会有大量重复的计算。所以这时按顺序推是个好办法。

            public int Fib(int n)
            {
                if (n == 0)
                    return 0;
                else if(n==1)
                    return 1;
    
                int num0 = 0;
                int num1 = 1;
                int num2 = 0;
                for (int i = 2; i <= n; i++)
                {
                    num2 = (num0 + num1)% 1000000007;
                    num0 = num1;
                    num1 = num2;
                }
    
                return num2;
            }
    
    

    2、题目2:青蛙跳台阶1

    https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/
    青蛙跳台阶1:青蛙一次可以挑1或2层台阶。求跳n层台阶有几种跳法。(n<=30)

    跳台阶其实就和斐波那契数列基本一样。不再重复写了。

    3、题目3:青蛙跳台阶2

    青蛙跳台阶2:青蛙一次可以挑1、2、、n-1、n台阶。求跳n层台阶有几种跳法。(n<=30)

    这道题的规律很好算:f(n) = 2^(n-1)

    我的解法:我是用快速幂算的

    long long CalculateWays(unsigned int n)
    {
        if(n==0)
            return 0;
        if(n==1)
            return 1;
        n--;
    
        long long result = 1;
        long long base = 2;
        while(n != 0){
            if(n%2 !=0){
                result *= base;
            }
            base *= base;
            n /= 2;
        }
    
        return result;
    }
    

    大佬的解法:位运算,一行代码搞定!

    long long CalculateWays(int n)
    {
        if(n==0)
            return 0;
        return 1<<(n-1);
    }
    

    4、题目4:青蛙跳台阶3

    青蛙跳台阶3:青蛙一次可以挑1或2层台阶。求跳n层台阶有几种跳法。(500>=n>=100)

    这道题规定的范围明显超过了long long的范围,所以用到了大整数加运算。

    我的解法:啰嗦的大整数+

    #include <iostream>
    #include <string>
    using namespace std;
    
    string CalculateWays(unsigned int n);
    
    string BigNumAdd(string s1,string s2);
    
    int main()
    {
    
        int n;
        cin>>n;
        if(n<=0){
            cout<<"输入范围错误";
        }
        else{
            cout<<CalculateWays(n);
        }
    
        return 0;
    }
    
    string CalculateWays(unsigned int n)
    {
        if(n==1)
            return "1";
        if(n==2)
            return "2";
        string lastlast = "1";
        string last = "2";
        string result = "0";
        for(int i=3;i<=n;i++){
            result = BigNumAdd(lastlast,last);
            lastlast = last;
            last = result;
        }
        return result;
    }
    
    string BigNumAdd(string s1,string s2)
    {
        int len1 = s1.size()-1;
        int len2 = s2.size()-1;
        string result = "";
        int carry = 0;
    
        //先算两个数都有的位
        while(len1>=0 && len2>=0){
            int add = s1[len1] - 48 + s2[len2] - 48 + carry;
            carry = add/10;
            add%=10;
    
            char addChar = add+48;
            result = addChar + result;
            len1--;
            len2--;
        }
    
        //再算位数多的
        while(len1>=0){
            int add = s1[len1] - 48 + carry;
            carry = add/10;
            add%=10;
    
            char addChar = add+48;
            result = addChar + result;
            len1--;
        }
        while(len2>=0){
            int add = s2[len2] - 48 + carry;
            carry = add/10;
            add%=10;
    
            char addChar = add+48;
            result = addChar + result;
            len2--;
        }
    	//最后是否进位
        if(carry > 0){
            char addChar = carry+48;
            result = addChar + result;
        }
        return result;
    }
    

    大佬的解法:优质的大整数+

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    string BigNumAddString(string s1,string s2)
    {
        string& longStr = s1.size()>=s2.size()?s1:s2;
        string& shortStr = s1.size()<s2.size()?s1:s2;
        //给短的字符串前面填充0
        shortStr.insert(0,longStr.size()-shortStr.size(),'0');
    
        string result;
        //给result预留足够的空间
        result.resize(s1.size()+s2.size()+1);
    
        //取各自最后一个字符的下标(要从后向前加)
        int longIndex = longStr.size()-1;
        int shortIndex = shortStr.size()-1;
        int resultIndex = result.size()-1;
        //进位标志
        int carry = 0;
    
        //加运算
        while(shortIndex>=0){
            int add = longStr[longIndex--] - '0' + shortStr[shortIndex--] - '0' + carry;
            carry = add/10;
            result[resultIndex--] = add%10 + '0';
        }
        //最后是否进位
        if(carry > 0){
            result[resultIndex--] = carry + '0';
        }
        //截取从这个参数下标开始一直到结尾(把前面多余的0截掉)
        result = result.substr(resultIndex+1);
        return result;
    }
    
    string CalculateWays(unsigned int n)
    {
        //也可以使用一个数组,把每次计算结果存进去
        if(n==1)
            return "1";
        if(n==2)
            return "2";
        string lastlast = "1";
        string last = "2";
        string result = "0";
        for(int i=3;i<=n;i++){
            result = BigNumAddString(lastlast,last);
            lastlast = last;
            last = result;
        }
        return result;
    }
    
    int main()
    {
        int n;
        cin>>n;
        if(n<=0){
            cout<<"输入范围错误"<<endl;
        }
        else{
            cout<<CalculateWays(n);
        }
    
        return 0;
    }
    

    5 新知识

    string和一些容器可以使用resize预分配空间,这样可以直接使用对象+[]形式赋值。

  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/12039743.html
Copyright © 2011-2022 走看看