1.用定义的递归算法
f(n)=f(n-1)+f(n-2)
指数级别,因为不断的重复计算,很多冗余
public static int Fibonacci1(int n)
{ if (n<=1) return n;
return Fibonacci1(n-1)+Fibonacci1(n-2);
}
2.用定义的迭代算法
线性,技巧是存下来,和动态规划的思想有些一致。
public static int Fibonacci2(int n)
{ int a=0;int b=1;
if (n==0) return 0;
while(n>1)
{
int c=a;
a=b;
b=c+b;
n--;
}
return b;
}
3.公式法
f(n)为Φ^n/√5取最近的整数,Φ=(1+√5)/2.
这种方法必须注意精度
用double来计算时会发现n=37时答案已经不准了
public static int Fibonacci3(int n)
{ double a=(1+Math.sqrt(5))/2;
int m=(int)(Math.pow(a, n)/Math.sqrt(5));
if((n&1)==1) m++;//当n为奇数时,是取整加一
return m;
}
这种方法效率取决于指数的计算。如果是直接相乘是线性的,如果用减半的方法,可以得到对数级别的。
4.使用某个等式
(1) { f ( n − 1 ) f ( n ) f ( n ) f ( n + 1 ) } = { 0 1 1 1 } n , n > = 1 \left\{ \begin{matrix} f(n-1)&f(n) \\ f(n) &f(n+1)\\ \end{matrix} \right\} \tag{1}= \left\{ \begin{matrix} 0&1 \\ 1 & 1\\ \end{matrix} \right\}^n,n>=1 {f(n−1)f(n)f(n)f(n+1)}={0111}n,n>=1(1)
对数级别的
//矩阵乘法 两个方阵a、b乘积
public static int[][]Matrix_Multiply(int a[][],int b[][],int n)
{int c[][]=new int[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
c[i][j]+=a[i][k]*b[k][j];
return c;
}
//矩阵快速幂(log n)
public static int Fibonacci4(int n)
{ int multi[][]= {{1,0},{0,1}};//单位矩阵
int x[][]= {{0,1},{1,1}};
while(n>0)
{
if((n&1)==1)
multi=Matrix_Multiply(multi,x,2);
x=Matrix_Multiply(x,x,2);
n>>=1;//相当于n=n/2
}
return multi[0][1];
}