Fibonacci的几种方法讨论

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 &gt; = 1 \left\{ \begin{matrix} f(n-1)&amp;f(n) \\ f(n) &amp;f(n+1)\\ \end{matrix} \right\} \tag{1}= \left\{ \begin{matrix} 0&amp;1 \\ 1 &amp; 1\\ \end{matrix} \right\}^n,n&gt;=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];	
	}

猜你喜欢

转载自blog.csdn.net/weixin_41677899/article/details/84258030
今日推荐