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预分配空间,这样可以直接使用对象+[]形式赋值。

  • 相关阅读:
    三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
    迭代器、生成器、面向过程编程
    wxpython 开发sheet
    演示生命周期和重定向
    wxpython 给框架增加菜单栏,工具栏和状态栏
    wxpython 开发俄罗斯方块
    关于重构代码的一些想法
    python 基于GUI 获取鼠标位置
    转载一篇文章 python程序在安卓手机上使用
    wxpython开发一个小游戏(一)
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/12039743.html
Copyright © 2011-2022 走看看