【剑指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;
    }
};
posted @ 2021-01-14 16:38  xxxuanei  阅读(423)  评论(0编辑  收藏  举报