剑指offer:面试题10- I. 斐波那契数列

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入:n = 2
输出:1

示例 2:

输入:n = 5
输出:5

提示:

0 <= n <= 100

解题:

方法一:递归

(1)递归:函数自己调用自己
(2)递归的"缺陷":递归到一定程度,会发生"栈溢出"
(3)递归的"时间复杂度":递归总次数*每次递归的次数
(4)递归的"空间复杂度":递归的深度*每次递归空间的大小(注意:"每次递归空间的大小"是个常数,可以基本忽略不计)
    递归的"深度":树的高度(递归的过程是一个"二叉树")

  • 时间复杂度

假设n对应复杂度T(n),由于if( n <= 1 )执行1次,f(n-1)执行1次,f(n-2)执行1次,然后f(n-1)和f(n-2)执行一次,因此有T(n)=T(n-1)+T(n-2)+4,忽略次要项,得到T(n)=T(n-1)+T(n-2),根据数学知识可得通项式为

下面继续分析下,不通过数学计算,估算其上下极限

上限:令T(n-2)约等于T(n-1),则T(n)=T(n-1)+T(n-2)=2T(n-1)=2*2*T(n-2)=....=2^n*T(0)=2^n,即为O(2^n)

下限:令T(n-1)约等于T(n-2),则T(n)=T(n-1)+T(n-2)=2T(n-2)=2*2*T(n-4)=....=2^(n/2)*T(0)=2^(n/2),即为O(2^(n/2))

所以最后可得到结果,其时间复杂度结果位于O(2^(n/2))和O(2^n)之间

  • 空间复杂度

跟所有递归调用一样,每次调用一次,都会进行压栈操作,因此下面分析函数调用时栈空间情况,要求f(n)会执行f(n-1)+f(n-2)需要压栈一次,然后求f(n-1)会执行f(n-2)+f(n-3)需要压栈一次,....,最后直到到f(1),这里以f(5)为例,那么栈情况如下图所示

剑指offer:面试题10- I. 斐波那契数列_第1张图片

递归算法的空间复杂度:递归的深度*每次递归所需的辅助空间的个数
而树的高度即为递归的深度。
则易知空间复杂度为O(n)

class Solution {
public:
    int fib(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        return (fib(n-1)+fib(n-2))%1000000007;
    }
};

方法二:动态规化法

动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划(DP)。

时间复杂度O(n),空间复杂度O(1)

class Solution {

public:
    int fib(int n) {
        if(n==0) return 0;
        int func1=0;
        int func2=1;
        for(int i=2;i<=n;i++) {
            int temp=f2;
            func2=(func1+func2)%1000000007;
            func1=temp;
        }   
        return func2;
    }
};

 

你可能感兴趣的:(剑指offer)