题目难度:入门
考察内容:递推,dp
题目内容:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
题目分析
首先我们都知道斐波那契数列的递推式子为f[i]=f[i-1]+f[i-2],我们要知道f[n]就要知道f[n-1],f[n-2],要是到f[n-1]就要知道f[n-2],f[n-3]。。。很明显这可以用递归来解决,递归的终止条件就是我们知道的f[0]=0,f[1]=1
于是我们有了一种解法
算法1(递归)
代码如下
class Solution { public: int Fibonacci(int n) { if(n==0)return 0;//f[0]=0 if(n==1)return 1;//f[1]=1 //终止条件 return Fibonacci(n-1)+Fibonacci(n-2);//f[n]=f[n-1]+f[n-2] } };
复杂度分析:时间复杂度,每次调用f[n-1],f[n-2]所以时间复杂度为O(2^n)
空间复杂度,没有额外空间,空间复杂度O(1)
可以发现时间复杂度太高
算法2(记忆化搜索)
可以发现有很多值是重复调用的,浪费了大量时间,可以记录每次的值,下次再碰到可以直接O(1)查询
代码如下
class Solution { public: int f[40]={0}; int Fibonacci(int n) { if(f[n])return f[n]; //如果f[n]已经求出了,直接调用即可 if(n==0)return 0;//f[0]=0 if(n==1)return 1;//f[1]=1 //终止条件 f[n]=Fibonacci(n-1)+Fibonacci(n-2);//f[n]=f[n-1]+f[n-2] return f[n]; } };
复杂度分析:时间复杂度,f[i]只会搜索一次,所以时间复杂度为O(n)
空间复杂度,有额外空间记录f[i],空间复杂度O(n)
空间复杂度达到了O(n)
继续优化
算法3(递推)
反向考虑,我们知道了f0,f1,所以f2=f0+f1,我们知道了f2,所以f3=f2+f1。。。发现可以直接递推,但是空间复杂度还是O(n)的,每次只用到了两个变量fi-1,fi-2,所以可以只设置两个变量a,b,ans=a+b,然后递推,a=b,b=ans.
代码如下
class Solution { public: int Fibonacci(int n) { long long a=1,b=1,ans=1; //a表示f[i-2],b表示f[i-1] if(n==0)return 0; //特判0 for(int i=3;i<=n;i++) ans=a+b,a=b,b=ans; //f[n]=a+b,f[i-2]=b,f[i-1]=ans return ans; } }; **复杂度分析:**时间复杂度,f[i]只会搜索一次,所以时间复杂度为O(n) **空间复杂度**,没有额外空间,空间复杂度O(1)