Fabonacci数列

来源:互联网 发布:杭州知味观礼盒 编辑:程序博客网 时间:2024/05/01 13:18

  面试此题时,如果回答递归求解,那就贻笑大方了

int fabonacci(int n){if(n == 0)return 0;if(n == 1)return 1;return fabonacci(n - 1) + fabonacci(n - 2);}


上述复杂度是指数级的,O(2^n)

如果用表来存储可以降低到O(n)

#include <iostream>using namespace std;#define MAX 20int fabonacci(int n, int *table){if(n == 0)return 0;if(n == 1)return 1;if(table[n - 1])return table[n - 1];table[n - 1] = fabonacci(n - 1, table) + fabonacci(n - 2, table);return table[n - 1];}void main(){int *table = new int[MAX];memset(table, 0, sizeof(int) * MAX);for(int i = 0; i < MAX; i++) {int result = fabonacci(i, table);cout << "result[" << i << "]" <<  " = " << result << endl;if(i && i % 10 == 0)cout << endl;}delete[] table;}


其实面试官最希望听到的是下面的解法:

/*利用公式[f(n), f(n-1)] = [f(n-1), f(n-2)]*A;矩阵A是x2矩阵*//*  * Copyright (c) 2011 alexingcool. All Rights Reserved.  */ #include <iostream>#include <algorithm>#include <cassert>using namespace std;int array[] = {1, 1, 1, 0};const int size = sizeof array / sizeof *array;class Matrix{public:Matrix(int (&array)[size]) {for(int i = 0; i < N; i++)for(int j = 0; j < N; j++)data[i][j] = array[i * N + j];}Matrix() {for(int i = 0; i < N; i++)for(int j = 0; j < N; j++)data[i][j] = 0;}Matrix(const Matrix &rhs) {for(int i = 0; i < N; i++)for(int j = 0; j < N; j++)data[i][j] = rhs.data[i][j];}int getFabonacci() { return data[0][0] + data[1][0]; }void printMatrix() {for(int i = 0; i < N; i++) {for(int j = 0; j < N; j++) {cout << data[i][j] << " ";}cout << endl;}}void copy(const Matrix &rhs) {for(int i = 0; i < N; i++) {for(int j = 0; j < N; j++) {data[i][j] = rhs.data[i][j];}}}static int getSize() { return N; }friend const Matrix operator * (const Matrix &lhs, const Matrix &rhs);Matrix& operator *= (const Matrix &rhs);private:static const int N = 2;int data[N][N];};const int Matrix::N;Matrix& Matrix::operator *=(const Matrix &rhs){Matrix result;for(int i = 0; i < N; i++) {for(int j = 0; j < N; j++) {for(int k = 0; k < N; k++) {result.data[i][j] += data[i][k] * rhs.data[k][j];}}}copy(result);return *this;}const Matrix operator * (const Matrix &lhs, const Matrix &rhs){Matrix result;int N = Matrix::getSize();for(int i = 0; i < N; i++) {for(int j = 0; j < N; j++) {for(int k = 0; k < N; k++) {result.data[i][j] += lhs.data[i][k] * rhs.data[k][j];}}}return result;}const Matrix matrixPow(const Matrix &base, int num){assert(num >= 0);int mat[size] = {1, 0, 0, 1};Matrix matrix(mat);Matrix temp = base;if(num < 0) {cerr << "num must be larger than 0" << endl;exit(0);}for(; num; num >>= 1) {if(num & 0x01)matrix *= temp;temp *= temp;}return matrix;}int fabonacci(int n){if(n <= 0)return 0;if(n == 1)return 1;Matrix matrix(array);matrix = matrixPow(matrix, n - 1);return matrix.getFabonacci();}void main(){Matrix mat(array);mat = matrixPow(mat, 3);mat.printMatrix();}尤其是关于N此方的计算,这个才是关键之所在,下面继续看下一道题,也是我在百度intern二面的题

实现函数double power(double base, int exponent),求base的exponent次方

我当时不假思索的写下下面的code:

double power(double base, int exponent){double result = 1.0;for(int i = 0; i < exponent; i++)result *= base;return result;}


随后面试官要求我写测试用例:

我按照正数、零、负数、极端写下以下用例

 极小值负数零正数极大值base-2^30-10.0010.02^30exponentnone-100102^30

所以上述代码得相应更改为:

double power(double base, int exponent){assert(exponent >= 0);double result = 1.0;if(exponent < 0) {cerr << "exponent must be larger than 0" << endl;return -1;}for(int i = 0; i < exponent; i++)result *= base;return result;}


然后他问我性能上能否优化,我想的方法不怎么好,但实质性还是O(logn)级的复杂度

base^exponent,将exponent除2,如果是偶数,就是base^(exponent >> 1) * base^(exponent >> 1),若是奇数,

则为base^(exponent >> 1) * base(exponent >> 1 + 1),然后一直这样分解。

他说这个方法代码不怎么好写,我觉得还是不难的,下面是我这个方法的代码

(其实,面试官对标准答案有先入为主的意识,对应聘者保持怀疑态度)

/*  * Copyright (c) 2011 alexingcool. All Rights Reserved. * 方法绝对原创,此方法转载请注明出处! * spend three hours, please respect my work. 7.13.2011*/ #include <iostream>#include <iterator>#include <algorithm>#include <cassert>using namespace std;#define INF 65535double _power(double base, int exponent, double *table){double result = 1.0;if(exponent == 0)return 1.0;if(table[exponent - 1] == 0 || table[exponent - 1] == INF) {if(exponent & 0x01) {if(exponent > 1) {table[(exponent >> 1) - 1] = _power(base, exponent >> 1, table);table[exponent >> 1] = _power(base, (exponent >> 1) + 1, table);return table[exponent >> 1] * table[(exponent >> 1) - 1];} else {table[0] = base;return table[0];}} else {table[(exponent >> 1) - 1] = _power(base, exponent >> 1, table);return table[(exponent >> 1) - 1] * table[(exponent >> 1) - 1];}}return table[exponent - 1];}double power(double base, int exponent){assert(exponent >= 0);int tableSize = exponent;double *table = new double[tableSize];for(int i = 0; i < tableSize; i++) {if(i >= (exponent >> 1) + 1)table[i] = INF;elsetable[i] = 0;}double result = _power(base, exponent, table);delete[] table;return result;}void main(){double base = 2.0;for(int exp = 0; exp < 32; exp++) {double result = power(base, exp);printf("%f^%d = %f\n", base, exp, result);}}

 上述方法的辅助空间其实可以缩小一半,只需要一个flag即可

double _power(double base, int exponent, double *table, bool flag){double result = 1.0;if(exponent == 0)return 1.0;if(table[exponent - 1] == 0 || flag == false) {flag = true;if(exponent & 0x01) {if(exponent > 1) {table[(exponent >> 1) - 1] = _power(base, exponent >> 1, table, flag);table[exponent >> 1] = _power(base, (exponent >> 1) + 1, table, flag);return table[exponent >> 1] * table[(exponent >> 1) - 1];} else {table[0] = base;return table[0];}} else {table[(exponent >> 1) - 1] = _power(base, exponent >> 1, table, flag);return table[(exponent >> 1) - 1] * table[(exponent >> 1) - 1];}}return table[exponent - 1];}double power(double base, int exponent){assert(exponent >= 0);int tableSize = exponent >> 1;bool flag = false;double *table = new double[tableSize + 1];for(int i = 0; i <= tableSize; i++) {table[i] = 0;}double result = _power(base, exponent, table, flag);delete[] table;return result;}

 

那么那位面试官想要的答案是啥呢,那就是上面Fibonacci数列关于求幂的方法

/*  * Copyright (c) 2011 alexingcool. All Rights Reserved.  */ #include <iostream>#include <iterator>#include <algorithm>#include <cassert>using namespace std;#define INF 65535double power(double base, int exponent){assert(exponent >= 0);double result = 1.0;for(; exponent; exponent >>= 1) {if(exponent & 0x01)result *= base;base *= base;}return result;}void main(){double base = 2.0;for(int i = 0; i < 32; i++) {double result = power(base, i);printf("%f^%d = %f\n", base, i, result);}}