Fabonacci数列

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

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 20

int 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^30
exponentnone-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 65535

double _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;
		else
			table[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 65535

double 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);
	}
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值