经典算法题总结:Fibonacci数列,从递归,动态规划,滚动数组,矩阵快速幂到通项公式

 题目链接:剑指 Offer 10- I. 斐波那契数列 - 力扣(LeetCode)

Fibonacci数列定义:

递归

核心是一个递归边界和递归体,复杂度分析可画递归树可得,时间复杂度是O(2^N),这是一个估算的上界,递归树最坏情况并不是满二叉树,数学上已经有证明出有通项公式可以表示:

空间复杂度和递归调用时的栈深有关是O(N),显然有很多次的重复调用:

class Solution {

    public int fib(int n) {
        if(n == 0 || n == 1) {
            return n;
        }
        return fib(n - 1) + fib(n - 2);
    }

}

动态规划

class Solution {

    public int fib(int n) {
        if(n == 0) {
            return 0;
        }
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2; i <= n; i++) {
            dp[i] = dp[i-1] + dp[i-2];
            dp[i] %= 1000000007;
        }
        return dp[n];
    }

}

这里为啥要对1000000007(1e9+7)取模呢,因为为了防止出现溢出的问题,当然你也可以抛出一个异常,1000000007是一个足够大的质数,这意味着没有公约数。

// 使用滚动数组进行优化空间复杂度
class Solution {

    public int fib(int n) {
        if(n <= 1) {
            return n;
        }
        int a = 0, b = 1, sum = 1;
        for(int i = 2; i < n; i++) {
            a = b;
            b = sum;
            sum = (a + b) % 1000000007;
        }
        return sum;
    }

}

矩阵快速幂

矩阵性质:

快速幂:

 这样就可以减少不必要的计算,比如2^10 = 2^5 * 2^5,少计算了4次。

通项公式法

这个快用之前介绍的通项公式直接可以得出答案时间和空间复杂度都是O(1)。

推导:https://www.zhihu.com/question/25217301/answer/30247743

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值