斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……
F(n)={1 n=0,1
F(n-1)+F(n-2) n>1
一、由递归算法可得:
public static int Fibonacci_Solution1(int n)
{
if(n<=1) return 1;
return Fibonacci_Solution1(n-1)+Fibonacci_Solution1(n-2);
}
缺点:递归由于调用函数自身,有时间和空间的消耗,函数的调用机制可由下表示:
1 、建立栈空间
2 、保护现场(将当前主调函数的执行状态和返回地址保存在栈中)
3、为被调函数的局部变量(包括形参)分配栈空间,并将实参值传递给形参。
4、执行被调函数直至返回语句或函数结束处
5、释放被调函数的所有局部变量栈空间
6、恢复现场。取出主调函数的执行状态及返回地址,释放栈空间。
递归的本质是将一个问题分解成两个或者多个小问题,如果小问题存在相互重叠的部分,那么就存在重复的计算。
递归还可能引起:调用栈溢出。每一次调用函数都在内存栈中分配空间,而每个进程的栈的容量是有限的。当递归调用的层级太多时,就会超出栈的容量。
二、迭代法(避免重复计算,保留中间项,从下往上)
long 和 int 范围是[-2^31,2^31-1],即-2147483648~2147483647,而unsigned范围是[0,2^32-1],即0~4294967295,所以常规的32位整数只能够处理40亿左右,当遇到比40亿大的多的数就要用到64位。 long long / unsigned long long 一般是Linux下申明方式、如:G++。
windows下需要用long long或,__int64配合%I64d。而在UNIX、Linux中必须使用标准C规定的long long配合%lld。
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include "iostream"
using namespace std;
// ====================方法2:循环====================
long long Fibonacci_Solution2(unsigned n)
{
int result[2] = {0, 1};
if(n < 2)
return result[n];
long long fibNMinusOne = 1;
long long fibNMinusTwo = 0;
long long fibN = 0;
for(unsigned int i = 2; i <= n; ++ i)
{
fibN = fibNMinusOne + fibNMinusTwo;
fibNMinusTwo = fibNMinusOne;
fibNMinusOne = fibN;
}
return fibN;
}
int _tmain(int argc, _TCHAR* argv[])
{
long long a= Fibonacci_Solution2(100);
printf("%I64u\n",a);
//std::cout<<a<<endl;
system("pause");
return 0;
}
迭代法的时间复杂度为O(n),使用的内存空间也不会动态上涨。
三、通项公式法
F(n)=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}
具体推导过程可参考:1、http://baike.baidu.com/link?url=nVfTTJJdRBbCsaNWnL0IZInkk8RCDrfqVtJKFQEf98H9L0lDV6zAxBFuch_Cg0cU
2、http://blog.163.com/zhuxun2@126/blog/static/3631555720071024105814506/
function y = Fib(n)
sr5 = sqrt(5);
y = uint32((((1 + sr5) / 2) ^ n - ((1 - sr5) / 2) ^ n) / sr5);
end
该方法的时间复杂度貌似为O(1),但我们还应该考虑乘方运算的时间消耗。不加特别优化时,用乘法实现n次乘方的时间复杂度为O(n)。考虑到浮点数计算效率和精度问题。