zoukankan      html  css  js  c++  java
  • 【剑指offer】10 斐波那契数列

    为什么要Mod 1e9+7

    • 为什么要模1000000007(跟我念,一,八个零,七)。

      1. 大数相乘,大数的排列组合等为什么要取模
        • 1000000007是一个质数(素数),对质数取余能最大程度避免结果冲突/重复
        • int32位的最大值为2147483647,所以对于int32位来说1000000007足够大。
        • int64位的最大值为2^63-1,用最大值模1000000007的结果求平方,不会在int64中溢出。
        • 所以在大数相乘问题中,因为(a∗b)%c=((a%c)∗(b%c))%c,所以相乘时两边都对1000000007取模,再保存在int64里面不会溢出。
      2. 这道题为什么要取模,取模前后的值不就变了吗?
        • 确实:取模前 f(43) = 701408733, f(44) = 1134903170, f(45) = 1836311903, 但是 f(46) > 2147483647结果就溢出了。
        • 取模后 f(43) = 701408733, f(44) = 134903163 , f(45) = 836311896, f(46) = 971215059没有溢出。
        • 取模之后能够计算更多的情况,如 f(46)
        • 这道题的测试答案与取模后的结果一致。
      • 总结一下,这道题要模1000000007的根本原因是标准答案模了1000000007。不过大数情况下为了防止溢出,模1000000007是通用做法,原因见第一点。

    题目1

    • 让你求斐波那契数列

    思路

    • 方法1:一开始我一看就开了个数组记录
    • 方法2:然后看别人的做法,发现我没必要开一个数组,因为这道题只要输出一次,所以存最近的两个值就好了
    • 方法3:然后看到了别人的又加又减的做法,感觉很interesting,其实思想是一样的
      • b = a + b
      • a = b - a
      • 最后结果是 b
    • 性能的话 感觉有点玄学,最下面的是方法1,中间方法2,最上面方法3
      • image-20210114160716564
      • 不知道是不是因为加加减减的原因,方法3的运行时间居然那么长,其实感觉方法1方法2运行时间为0也很奇怪

    代码

    // solution 2
    class Solution {
    public:
        int fib(int n) {
            if(n==0||n==1) return n;
            int a, b, tmp;
            const int MOD = 1000000007;
            a=0,b=1;
            for(int i=2;i<=n;i++){
                tmp = (a+b)%MOD;
                a = b;
                b = tmp;
            }
            return tmp;
        }
    };
    // solution 3
    class Solution {
    public:
        int fib(int n) {
            if(n==0||n==1) return n;
            int a, b, tmp;
            const int MOD = 1000000007;
            a=0,b=1;
            for(int i=2;i<=n;i++){
                b = a + b;
                a = b - a;
                b = b%MOD;
            }
            return b;
        }
    };
    

    题目2

    • 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
    • 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

    思考

    • 找规律,发现是斐波那契数列(毕竟上一题就是斐波那契数列)
    • 除此之外,我是这样理解
      • (f(i)):第 i 级台阶的跳法数
      • (f(i) = f(i-1)+f(i-2))
      • 由于只有两种跳跃方法,所以可以是:
        • i-1级时的跳法,然后现在跳1级
        • i-2级时的跳法,然后现在跳2级
      • 注意特殊值,0的时候要是1才行(题目也有要求n=0时的值要是1)

    代码

    class Solution {
    public:
        int numWays(int n) {
            const int MOD = 1000000007;
            if(n==0||n==1) return 1;
            int a = 1, b = 1, tmp;
            for(int i=2;i<=n;i++){
                tmp = (b + a)%MOD;
                a = b;
                b = tmp;
            }
            return b;
        }
    };
    
  • 相关阅读:
    MySQL实战45讲学习笔记:第二十四讲
    MySQL实战45讲学习笔记:第二十六讲
    MySQL实战45讲学习笔记:第二十三讲
    MySQL实战45讲学习笔记:第二十一讲
    MySQL实战45讲学习笔记:第二十二讲
    MySQL实战45讲学习笔记:第十七讲
    MySQL实战45讲学习笔记:第十四讲
    MySQL实战45讲学习笔记:第十三讲
    Web协议详解与抓包实战:HTTP1协议-内容协商是怎样进行的(8)
    Web协议详解与抓包实战:HTTP1协议-请求与响应的上下文(7)
  • 原文地址:https://www.cnblogs.com/xuwanwei/p/14278022.html
Copyright © 2011-2022 走看看