您的位置:首页 > 职场人生

面试题9:递归和非递归

2016-06-14 13:30 239 查看
1.题目:编写函数,计算斐波拉契数列的第n项。定义如图



分析:

这是一个经典的问题,很多人都会用递归的方法去解决,但是实际的效果真的可以用吗,如果采用递归的方法,在求斐波拉契数列第n项的过程中,不仅会存在重复计算的项,而且而且函数调用自身也是有时间和空间消耗的,涉及到往栈中压入数据和弹出数据,这将消耗大量的时间。而采用循环计算的方法则不会存在这种问题,时间复杂度为O(n)。关于计算斐波拉契数列第n项还有一种方法就是用矩阵相乘的方法。



用数学归纳法很容易证明,这样可以将时间复杂度缩短至O(lgn).

源码:

/*递归和非递归的比较*/
#include<iostream>
#include <time.h>
#include <cassert>
using namespace std;

// ====================方法1:递归====================
long long Fibonacci_Solution1(unsigned int n)
{

if (n <= 0)
return 0;

if (n == 1)
return 1;

return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
}

// ====================方法2:循环====================
long long Fibonacci_Solution2(unsigned n)
{
int result[2] = { 0, 1 };
if (n < 2)
return result
;

long long  fibNMinusOne = 1;
long long  fibNMinusTwo = 0;
long long  fibN = 0;
for (unsigned int i = 2; i <= n; ++i)//更新前两项的值
{
fibN = fibNMinusOne + fibNMinusTwo;

fibNMinusTwo = fibNMinusOne;
fibNMinusOne = fibN;
}

return fibN;
}
// ====================方法3:基于矩阵乘法====================
struct Matrix2By2
{
Matrix2By2
(
long long m00 = 0,
long long m01 = 0,
long long m10 = 0,
long long m11 = 0
)
:m_00(m00), m_01(m01), m_10(m10), m_11(m11)
{
}

long long m_00;
long long m_01;
long long m_10;
long long m_11;
};

Matrix2By2 MatrixMultiply
(
const Matrix2By2& matrix1,
const Matrix2By2& matrix2
)
{
return Matrix2By2(
matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);
}

Matrix2By2 MatrixPower(unsigned int n)
{
assert(n > 0);

Matrix2By2 matrix;
if (n == 1)
{
matrix = Matrix2By2(1, 1, 1, 0);
}
else if (n % 2 == 0)
{
matrix = MatrixPower(n / 2);
matrix = MatrixMultiply(matrix, matrix);
}
else if (n % 2 == 1)
{
matrix = MatrixPower((n - 1) / 2);
matrix = MatrixMultiply(matrix, matrix);
matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
}

return matrix;
}

long long Fibonacci_Solution3(unsigned int n)
{
int result[2] = { 0, 1 };
if (n < 2)
return result
;

Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
return PowerNMinus2.m_00;
}
int main()
{

long long result;
clock_t start, finish;
double duration;
start = clock();
result = Fibonacci_Solution1(40);//递归方法计算
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "递归的结果是: "<<result<<"--"<<"递归耗时:" << duration << "秒" << endl;
start = clock();
result = Fibonacci_Solution2(40);//循环方法计算
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "循环的结果是: " << result << "--" << "循环耗时:" << duration << "秒" << endl;
start = clock();
result = Fibonacci_Solution3(40);//矩阵相乘的方法计算
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "矩阵乘法的结果是: " << result << "--" << "矩阵相乘耗时:" << duration << "秒" << endl;

system("PAUSE");
return 0;
}


结果:



相关的变形题目:

1.青蛙跳台阶的问题,青蛙一次可以跳上一级台阶,也可以跳两级台阶,问青蛙跳上n级的台阶的总共的跳法。

2.用2x1的小矩形覆盖更大的矩形的问题,n个2x1的小矩形覆盖一个2xn的大矩形的方法总数。

这些都是类似斐波拉契数列的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: