1 //计算斐波那契数列 f(n) 2 3 #include <iostream> 4 #include <cmath> 5 using namespace std; 6 7 long fib1(int n){ 8 /*递归程序1:这种是最原始的想法,这样的做法会重复调用,做很多无用的工作。下面是优化的几种方法 */ 9 if (n <= 2){ 10 return 1; 11 } 12 else{ 13 return fib1(n-1) + fib1(n-2); 14 } 15 } 16 17 long fib(int n, long a, long b, int count){ 18 if (count == n) 19 return b; 20 return fib(n, b, a+b, ++count); 21 } 22 23 long fib2(int n){ 24 /* 递归程序2:这种递归的写法比fib1进步了不少,它略过了很多fib1中重复计算的部分。 25 但是递归写法,时间复杂度依然很高,近似为线性时间O(n),但比起下面的迭代循环仍然没有优势 */ 26 return fib(n, 0, 1, 1); 27 } 28 29 30 long fib3 (int n){ 31 /* 迭代解法:这里算法复杂度显然为O(n) , 32 这个解法目前来看是最好的解法,算法既不复杂,而且在时间复杂度和空间复杂度上都有保证 */ 33 long x = 0, y = 1; 34 for (int j = 1; j < n; j++){ 35 y = x + y; 36 x = y - x; 37 } 38 return y; 39 } 40 41 /* 这里也可以将每次计算的结果存储下来,这就是大名鼎鼎的以“空间换时间”,下面就是用空间换时间的程序 42 43 long fib3(int n){ 44 if(n==0) return 0; 45 long data[n]; 46 data[0]=0,data[1]=1; 47 for(int i=2;i<=n;i++){ 48 data[i]=data[i-1]+data[i-2]; 49 } 50 return data[n]; 51 } 52 53 */ 54 55 class Matrix{ 56 public: 57 long matr[2][2]; 58 Matrix(const Matrix&rhs); 59 Matrix(long a, long b, long c, long d); 60 Matrix& operator=(const Matrix&); 61 62 friend Matrix operator*(const Matrix& lhs, const Matrix& rhs){ 63 Matrix ret(0,0,0,0); 64 ret.matr[0][0] = lhs.matr[0][0]*rhs.matr[0][0] + lhs.matr[0][1]*rhs.matr[1][0]; 65 ret.matr[0][1] = lhs.matr[0][0]*rhs.matr[0][1] + lhs.matr[0][1]*rhs.matr[1][1]; 66 ret.matr[1][0] = lhs.matr[1][0]*rhs.matr[0][0] + lhs.matr[1][1]*rhs.matr[1][0]; 67 ret.matr[1][1] = lhs.matr[1][0]*rhs.matr[0][1] + lhs.matr[1][1]*rhs.matr[1][1]; 68 return ret; 69 } 70 }; 71 72 Matrix::Matrix(long a, long b, long c, long d){ 73 this->matr[0][0] = a; 74 this->matr[0][1] = b; 75 this->matr[1][0] = c; 76 this->matr[1][1] = d; 77 } 78 79 Matrix::Matrix(const Matrix &rhs){ 80 this->matr[0][0] = rhs.matr[0][0]; 81 this->matr[0][1] = rhs.matr[0][1]; 82 this->matr[1][0] = rhs.matr[1][0]; 83 this->matr[1][1] = rhs.matr[1][1]; 84 } 85 86 Matrix& Matrix::operator =(const Matrix &rhs){ 87 this->matr[0][0] = rhs.matr[0][0]; 88 this->matr[0][1] = rhs.matr[0][1]; 89 this->matr[1][0] = rhs.matr[1][0]; 90 this->matr[1][1] = rhs.matr[1][1]; 91 return *this; 92 } 93 94 Matrix power(const Matrix& m, int n){ 95 if (n == 1) 96 return m; 97 if (n%2 == 0) 98 return power(m*m, n/2); 99 else 100 return power(m*m, n/2) * m; 101 } 102 103 long fib4 (int n){ 104 /* 矩阵乘法:二分法进一步优化程序,时间复杂度为O(log(n)) */ 105 Matrix matrix0(1, 1, 1, 0); 106 matrix0 = power(matrix0, n-1); 107 return matrix0.matr[0][0]; 108 } 109 110 long fib5(int n){ 111 /* 公式法:终极必杀,直接套用表达式求解,时间复杂度为O(1). 112 不过有瑕疵的一点就是受制于库函数实现开方和乘方的效率,具体时间复杂度上考虑到上一点,估计也是 O(log(n)) */ 113 double z = sqrt(5.0); 114 double x = (1 + z)/2; 115 double y = (1 - z)/2; 116 return (pow(x, n) - pow(y, n))/z + 0.5; 117 } 118 119 int main(){ 120 cout << fib1(45) << endl; 121 cout << fib2(45) << endl; 122 cout << fib3(45) << endl; 123 cout << fib4(45) << endl; 124 cout << fib5(45) << endl; 125 return 0; 126 }