面试题9:递归和非递归
2016-06-14 13:30
239 查看
1.题目:编写函数,计算斐波拉契数列的第n项。定义如图
分析:
这是一个经典的问题,很多人都会用递归的方法去解决,但是实际的效果真的可以用吗,如果采用递归的方法,在求斐波拉契数列第n项的过程中,不仅会存在重复计算的项,而且而且函数调用自身也是有时间和空间消耗的,涉及到往栈中压入数据和弹出数据,这将消耗大量的时间。而采用循环计算的方法则不会存在这种问题,时间复杂度为O(n)。关于计算斐波拉契数列第n项还有一种方法就是用矩阵相乘的方法。
用数学归纳法很容易证明,这样可以将时间复杂度缩短至O(lgn).
源码:
结果:
相关的变形题目:
1.青蛙跳台阶的问题,青蛙一次可以跳上一级台阶,也可以跳两级台阶,问青蛙跳上n级的台阶的总共的跳法。
2.用2x1的小矩形覆盖更大的矩形的问题,n个2x1的小矩形覆盖一个2xn的大矩形的方法总数。
这些都是类似斐波拉契数列的问题。
分析:
这是一个经典的问题,很多人都会用递归的方法去解决,但是实际的效果真的可以用吗,如果采用递归的方法,在求斐波拉契数列第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的大矩形的方法总数。
这些都是类似斐波拉契数列的问题。
相关文章推荐
- 面试题22 栈的压入、弹出序列
- Java程序员也应该知道的系统知识系列之(网卡,cpu,内存,硬盘,虚拟化)
- 编程之法:面试和算法心得
- 要准备了:JAVA面试题及答案汇总
- 腾讯面试全程
- 面试腾讯全过程
- 程序员,应该掌握的英语词汇
- 面试题21 包含Min函数的栈
- 非技术相关的面试技巧(文章内容来自他人博客)
- 升级您的ERP系统
- 写给嵌入式程序员的循环冗余校验(CRC)算法入门引导
- Android面试题(文章内容来自他人博客)
- 与WWDC大会同步,黑马程序员iOS4.0课程震撼出炉
- Java笔试面试题整理第八波
- 面试题47-2:不使用新的变量,交换两个变量的值
- 面试题47:不用加减乘除做加法
- 程序员面试50题(1)—查找最小的k个元素[算法]
- 运维面试题和答案
- 求职前夕的不眠夜
- 大数相加 面试题