package zieckey.datastructure.study.recursion;
import java.math.BigInteger; import java.util.Date;
public class Fibonacci { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub
int n = 120000; Fibonacci r = new Fibonacci( ); long begin, done; begin = new Date( ).getTime( ); System.out.println( r.funLastLiuBing( n ) ); done = new Date( ).getTime( );
System.out.println( "funLastLiuBing:花费时间:" + ( done - begin ) + "ms" );
begin = new Date( ).getTime( ); System.out.println( "fibonacciMatrixBigInteger: " + r.fibonacciMatrixBigInteger( n ) ); done = new Date( ).getTime( ); System.out.println( "fibonacciMatrixBigInteger:花费时间:" + ( done - begin ) + "ms" ); begin = new Date( ).getTime( ); System.out.println( "fibonacciMatrixMultiply2NBigInteger: " + r.fibonacciMatrixBigInteger( n ) ); done = new Date( ).getTime( ); System.out.println( "fibonacciMatrixMultiply2NBigInteger:花费时间:" + ( done - begin ) + "ms" );
}
/** * 计算: f(n) = n + 1 (n <2)? f(n) = f[n/2] + f[n/4] (n >= 2) * * @param 传入参数 * n>0 的正整数 * @return */ public int func( int n ) { if ( 2 > n ) { return n + 1; } else { return func( (int)n / 2 ) + func( (int)n / 4 ); } }
/** * 计算: * f(n) = 0 (n = 0) * f(n) = 1 (n = 1)? * f(n) = f[n-1] + f[n-2] (n >= 2) * * @param n * Fibonacci 序列 * @return */ public long fibonacciRecursion( int n ) { if ( 0 == n ) { return 0; } else if ( 1 == n ) { return 1; } else { return fibonacciRecursion( n - 1 ) + fibonacciRecursion( n - 2 ); } } /** * 计算: * f(n) = 0 (n = 0) * f(n) = 1 (n = 1) * f(n) = f[n-1] + f[n-2] (n >= 2) * * @param n * Fibonacci 序列 * @return */ public long fibonacciAdd2N( int n ) { if ( 0 == n ) { return 0; } else if ( 1 == n ) { return 1; } else { long n0 = 0; long n1 = 1; long fn = 0; for ( int i = 2; i <= n; i++ ) { fn = n1 + n0; n0 = n1; n1 = fn; } return fn; } }
/** * 可以计算无限大的数 * @param n * @return */ public BigInteger fibonacciAdd2NBigInteger( int n ) { if ( 0 == n ) { return new BigInteger("0"); } else if ( 1 == n ) { return new BigInteger("1"); } else { BigInteger n0 = BigInteger.ZERO; BigInteger n1 = BigInteger.ONE; BigInteger fn = BigInteger.ZERO; for ( int i = 2; i <= n; i++ ) { fn = n1.add( n0 ); n0 = n1; n1 = fn; } return fn; } } /** * * 方法,通过矩阵运算,可以得到最优的算法复杂度,O(log2(n)) * |f(n) | = |1 1 | |f(n-1)|= |1 1 | |1 1 | |f(n-2)|..... * |f(n-1)| = |1 0 | |f(n-2)|= |1 0 | |1 0 | |f(n-3)|..... * @param n * @return */ public long fibonacciMatrix( int n ) { if ( 1 == n || 2 == n ) { return 1; }
long[][] a = { { 1, 1 }, { 1, 0 } }; long[][] r = new long[2][2];
r = calcMatrixNPower( a, n - 2 );
/* * 最后结果: * * |f(n) | = |r00 r01 ||f(1)| = r00 + r01 * |f(n-1)| = |r10 r11 ||f(2)| = r10 + r11 * */ return r[0][0] + r[0][1];//最后result与
} /** * 可以计算无限大的数 * * 方法,通过矩阵运算,可以得到最优的算法复杂度,O(log2(n)) |f(n) | = |1 1 | |f(n-1)|= |1 1 | |1 1 | |f(n-2)|..... |f(n-1)| = |1 0 | |f(n-2)|= |1 0 | |1 0 | |f(n-3)|..... * @param n * @return */ public BigInteger fibonacciMatrixBigInteger( int n ) { if ( 1 == n || 2==n ) { return new BigInteger("1"); } BigInteger temp = new BigInteger("0"); BigInteger[][] a = {{BigInteger.ONE,BigInteger.ONE},{BigInteger.ONE,BigInteger.ZERO}}; BigInteger[][] result = new BigInteger[2][2]; result = calcMatrixNPowerBigInteger( a, n-2 ); temp = result[0][0]; temp = temp.add( result[0][1] ); return temp; } /** * 可以计算无限大的数 * * 方法,通过矩阵运算,可以得到最优的算法复杂度,O(log2(n)) |f(n) | = |1 1 | |f(n-1)|= |1 1 | |1 1 | |f(n-2)|..... |f(n-1)| = |1 0 | |f(n-2)|= |1 0 | |1 0 | |f(n-3)|..... * @param n * @return */ public BigInteger fibonacciMatrixMultiply2NBigInteger( int n ) { if ( 1 == n || 2==n ) { return new BigInteger("1"); } BigInteger temp = new BigInteger("0"); BigInteger[][] a = {{BigInteger.ONE,BigInteger.ONE},{BigInteger.ONE,BigInteger.ZERO}}; BigInteger[][] result = {{BigInteger.ONE,BigInteger.ZERO},{BigInteger.ZERO,BigInteger.ONE}}; // result = calcMatrixNPowerBigInteger( a, n-2 );
//n-2次循环
for ( int i = 0; i < n-2; i++ ) { result = calcMatrixMultipleBigInteger( result, a ); } temp = result[0][0]; temp = temp.add( result[0][1] ); return temp; } /** * * @param * @param b * @return 矩阵a与矩阵b相乘的结果 */ public long[][] calcMatrixMultiple( long[][] a , long[][] b ) { long[][] result = new long[2][2]; result[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; result[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; result[1][0] = a[1][0] * b[0][0] + a[1][1]* b[1][0]; result[1][1] = a[1][0] * b[0][1] + a[1][1]* b[1][1]; return result; } /** * * @param a * @param n * @return 矩阵a的n次方结果 */ public long[][] calcMatrixNPower( long[][] a, int n ) { long[][] result = {{1,0},{0,1}};;//初始化为单位阵
long[][] temp = new long[2][2]; int log2n = 0; /** * 例如:n=25 * 外层for 3次循环 * 第一次 result = (a^2)^4 i=25 * 第二次 result = ((a^2)^4) * ((a^2)^3) i=9 * 第三次 result = (((a^2)^4)*((a^2)^3))*a i=1 * * 例如:n=24 * 外层for 2次循环 * 第一次 result = (a^2)^4 i=24 * 第二次 result = ((a^2)^4) * ((a^2)^3) i=8 */ for ( int i = n; i >= 1 ; i = i - (int)Math.pow( 2, log2n ) ) { temp = a;//初始化 temp 等于a
log2n = log2(i); //找到最大的 log2(i)
for ( int j = 0; j < log2n; j++ ) { temp = calcMatrixMultiple( temp, temp ); //计算(temp的平方)的log2n次方
} result = calcMatrixMultiple( result, temp ); } return result; }
/** * * 对方法calcMatrixANPower测试用的 * @param a * @param n * @return a的n次幂 */ public long testPower(int a, int n) { long result = 1; int temp = a; int log2n = 0; for ( int i = n; i >= 1 ; i = i - (int)Math.pow( 2, log2n ) ) { temp = a;//初始化 temp 等于a
log2n = log2(i); //找到最大的 log2(i)
for ( int j = 0; j < log2n; j++ )//计算(temp的平方)的log2n次方
{ temp = temp*temp; } result = result*temp; } return result; }
/** * * @param a * @param b * @return 矩阵a与矩阵b相乘的结果 */ public BigInteger[][] calcMatrixMultipleBigInteger( BigInteger[][] a, BigInteger[][] b ) { BigInteger[][] result = new BigInteger[2][2]; BigInteger temp = new BigInteger("0"); temp = a[0][0].multiply( b[0][0] ) ; result[0][0] = temp.add( a[0][1].multiply( b[1][0]) ) ;
temp = a[0][0].multiply( b[0][1] ) ; result[0][1] = temp.add( a[0][1].multiply( b[1][1]) ) ; temp = a[1][0].multiply( b[0][0] ) ; result[1][0] = temp.add( a[1][1].multiply( b[1][0]) ) ; temp = a[1][0].multiply( b[0][1] ) ; result[1][1] = temp.add( a[1][1].multiply( b[1][1]) ) ; return result; } /** * * @param a * @param n * @return 矩阵a的n次方结果 */ public BigInteger[][] calcMatrixNPowerBigInteger( BigInteger[][] a, int n ) { BigInteger[][] result = {{BigInteger.ONE,BigInteger.ZERO},{BigInteger.ZERO,BigInteger.ONE}}; BigInteger[][] temp = new BigInteger[2][2]; int log2n = 0; for ( int i = n; i >= 1 ; i = i - (int)Math.pow( 2, log2n ) ) { temp = a;//初始化 temp 等于a
log2n = log2(i); //找到最大的 log2(i)
for ( int j = 0; j < log2n; j++ ) { temp = calcMatrixMultipleBigInteger( temp, temp ); //计算(temp的平方)的log2n次方
} result = calcMatrixMultipleBigInteger( result, temp ); } return result; } /** * * @param n * @return 以2为底的log对数 */ public int log2( int n ) { int result = 0; result = (int) ( Math.log( n ) / Math.log( 2 ) ); return result; } }
|