斐波那契(Fibonacci)数列
问题描述
递归算法:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * Fibonacci数列递归求解 4 * @author DELL 5 * 6 */ 7 public class Fibonacci1 { 8 public static int fibonacci(int n){ 9 if(n<=0) 10 return 0; 11 else if(n==1) 12 return 1; 13 else 14 return fibonacci(n-1)+fibonacci(n-2); 15 } 16 public static void main(String[] args) { 17 int n = 3; 18 System.out.println("fibonacci("+n+") = "+fibonacci(n)); 19 20 } 21 22 }
我们的问题是:有没有更加优化的解法?
分析与解法
【解法一】递推关系的优化
上述递归算法中有着很多的重复计算,利用一个数组存储中间结果避免重复计算。时间复杂度为O(N),空间复杂度也为O(N)。
算法如下:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * Fibonacci数列求解 4 * 【解法一】递推关系的优化 5 * @author DELL 6 * 7 */ 8 public class Fibonacci2 { 9 private static int f[]; 10 public Fibonacci2(int n){ 11 f = new int[n+1]; 12 for(int i=0;i<n;i++){ 13 f[i]=-1; 14 } 15 } 16 public static int fibonacci(int n){ 17 if(n<=0){ 18 f[0]=0; 19 return 0; 20 } 21 else if(n==1){ 22 f[1]=1; 23 return 1; 24 } 25 else{ 26 if(f[n-1]==-1){ 27 if(f[n-2]==-1) 28 return fibonacci(n-1)+fibonacci(n-2); 29 else 30 return fibonacci(n-1)+f[n-2]; 31 }else{ 32 return f[n-1]+f[n-2]; 33 } 34 } 35 } 36 public static void main(String[] args) { 37 int n = 3; 38 new Fibonacci2(n); 39 System.out.println("fibonacci("+n+") = "+fibonacci(n)); 40 41 } 42 43 }
程序运行结果如下:
fibonacci(3) = 2
【解法二】采用非递归求解
算法如下:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * Fibonacci数列求解 4 * 【解法二】非递归 5 * @author DELL 6 * 7 */ 8 public class Fibonacci3 { 9 public static int fibonacci(int n){ 10 if(n<=0) 11 return 0; 12 else if(n==1) 13 return 1; 14 else{ 15 int f0 = 0,f1 = 1,f2 = 0; 16 for(int i=2;i<=n;i++){ 17 f2 = f0 + f1; 18 f0 = f1; 19 f1 = f2; 20 } 21 return f2; 22 } 23 } 24 public static void main(String[] args) { 25 int n = 3; 26 System.out.println("fibonacci("+n+") = "+fibonacci(n)); 27 28 } 29 30 }
程序运行结果如下:
fibonacci(3) = 2
【解法三】求解通项公式
算法代码如下:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * Fibonacci数列求解 4 * 【解法三】求解通项公式 5 * @author DELL 6 * 7 */ 8 public class Fibonacci4 { 9 public static long fibonacci(int n){ 10 double x = Math.sqrt(5); 11 double f = (x/5)*Math.pow((1+x)/2, n) - (x/5)*Math.pow((1-x)/2, n); 12 return Math.round(f); 13 } 14 public static void main(String[] args) { 15 int n = 3; 16 System.out.println("fibonacci("+n+") = "+fibonacci(n)); 17 18 } 19 20 }
程序运行结果如下:
fibonacci(3) = 2
【解法四】分治策略
要先导入JAMA:Java矩阵包
1 package chapter2shuzizhimei.fibonacci; 2 3 import Jama.Matrix; 4 5 /** 6 * Fibonacci数列求解 7 * 【解法四】分治策略 8 * @author DELL 9 * 10 */ 11 public class Fibonacci5 { 12 //求解矩阵A的n次方 13 public static Matrix MatrixPow(Matrix A, int n){ 14 int m = A.getColumnDimension(); 15 Matrix result = new Matrix(m,m); //生成全为0的矩阵 16 for(int i=0;i<m;i++){ //变成单位矩阵 17 result.set(i, i, 1); 18 } 19 Matrix temp = A; 20 while(n!=0){ 21 if((n&0x01)==1) 22 result = result.times(temp); //矩阵的乘法 23 temp = temp.times(temp); 24 n >>= 1; 25 } 26 return result; 27 } 28 //计算Fibonacci数列 29 public static long fibonacci(int n){ 30 if(n<=0) 31 return 0; 32 else if(n==1) 33 return 1; 34 else{ 35 Matrix A = new Matrix(2,2,1); //生成全为1的矩阵 36 A.set(1, 1, 0); 37 Matrix B = MatrixPow(A, n-1); 38 return (long) B.get(0, 0); 39 } 40 } 41 public static void main(String[] args) { 42 int n = 5; 43 System.out.println("fibonacci("+n+") = "+fibonacci(n)); 44 45 } 46 47 }
程序运行结果如下:
fibonacci(5) = 5
扩展问题
假设A(0)=1,A(1)=2,A(2)=2。对于n>2,都有A(K) = A(k-1) + A(k-2) +A(k-3)。
1. 对于任何一个给定的n,如何计算出A(n)?
2. 对于n非常大的情况,如n=260的时候,如何计算A(n) mod M (M<100000)呢?
问题1:非递归解法,代码如下:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * 扩展问题1求解 4 * 非递归 5 * @author DELL 6 * 7 */ 8 public class Fibonacci6 { 9 public static int A(int n){ 10 if(n<=0) 11 return 1; 12 else if(n==1||n==2) 13 return 2; 14 else{ 15 int f0 = 1,f1 = 2,f2 = 2,f3 = 0; 16 for(int i=3;i<=n;i++){ 17 f3 = f0 + f1 + f2; 18 f0 = f1; 19 f1 = f2; 20 f2 = f3; 21 } 22 return f3; 23 } 24 } 25 public static void main(String[] args) { 26 int n = 4; 27 System.out.println("A("+n+") = "+A(n)); 28 29 } 30 31 }
程序运行结果如下:
A(4) = 9
问题2:非递归解法,代码如下:
1 package chapter2shuzizhimei.fibonacci; 2 /** 3 * 扩展问题2求解 4 * 非递归 5 * @author DELL 6 * 7 */ 8 public class Fibonacci7 { 9 //计算A(n) mod m 10 public static long A(long n,long m){ 11 if(n<=0) 12 return 1; 13 else if(n==1||n==2) 14 return 2; 15 else{ 16 long f0 = 1,f1 = 2,f2 = 2,f3 = 0; 17 for(int i=3;i<=n;i++){ 18 f0 = f0%m; 19 f1 = f1%m; 20 f2 = f2%m; 21 f3 = f0 + f1 + f2; 22 f0 = f1; 23 f1 = f2; 24 f2 = f3; 25 } 26 return f3%m; 27 } 28 } 29 public static void main(String[] args) { 30 long n = (long) Math.pow(2, 10); 31 long m = 100; 32 System.out.println("A("+n+") = "+A(n,m)); 33 34 } 35 36 }
程序运行结果如下:
A(1024) = 97
时间: 2024-10-08 18:25:17