方法一: 递归法
int Fib(int n){
if(n==1 || n==2) return 1;
return Fib(n-1)+Fib(n-2);
}
递归法的时间复杂度为o(2^n)。
递归算法的程序看上去很简洁,但实际上运行起来却不如此,深度的递归会占用很多栈空间,容易造成溢出。另外在递归计算Fibonacci数列过程中有很多重复计算。比如,计算f(5)需要计算f(4),f(3)。计算f(4)时又要计算一遍f(3)。在n数字很大时,这样重复的计算非常耗时且没有意义。
方法二: 递推法(借用数组存储)
解决方法就是使用一个数组将算过的数保存起来,将递归法转为递推法。如果需要计算f(n),我们就从f(0)开始计算,一直计算到f(n)。
这样就消除了重复计算,因为每次计算新值都是从之前计算过的数组中取。递推法的时间复杂度为 O(n2),空间复杂度为 O(n)。
int Fibonacci(int n){
int F[n+1]; //创建一个数组,存储计算过的值
F[1] = 1;
F[2] = 1;
for(int i=3;i<=n;i++){
F[i]=F[i-1]+F[i-2];
}
return F[n];
}
方法三: 递推法优化(不用数组)
递推法其实还能够进行优化,可以不再使用数组存储,分析一下:在计算f(n)时我们只需要知道f(n-1)和f(n-2)两个值即可,即只保留数组中最后俩数即可,前面的元素已经没有存在的必要。因此我们使用两个变量来保存需要计算出f(n)的前两个元素即可。
int Fibonacci(int n){
int tmp,k=0,ans=1;
for(int i=2;i<=n;i++){
tmp=k;
k=ans;
ans=k + tmp;
}
return ans;
}
分别用k和tmp保存我们需要的两个值,初始k代表 f(0),ans代表f(1), 令tmp=k临时保存f(0),k保存f(1),计算f(2) = f(0) + f(1),即ans=k + tmp,当计算完f(2)后 ,f(0)的值我们已经不需要了,此时为了计算f(3)我们需要的是f(1)和刚刚计算好的f(2), 重复上述步骤,令tmp=k临时保存f(1),k保存刚刚计算好的f(2)的值ans,然后计算f(3) = f(2) + f(1),即ans=k + tmp。依次类推…
优化后算法的空间复杂度为O(1)。