首页
外语
计算机
考研
公务员
职业资格
财经
工程
司法
医学
专升本
自考
实用职业技能
登录
计算机
定义Fibonacci数列如下: 输入n,用最快的方法求该数列的第n项。
定义Fibonacci数列如下: 输入n,用最快的方法求该数列的第n项。
admin
2019-03-29
93
问题
定义Fibonacci数列如下:
输入n,用最快的方法求该数列的第n项。
选项
答案
#include
/////////////////////////////////////////////////////////////////////// // A 2 by 2 matrix /////////////////////////////////////////////////////////////////////// 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; }; /////////////////////////////////////////////////////////////////////// // Multiply two matrices // Input: matrix1 - the first matrix // matrix2 - the second matrix //Output: the production of two matrices /////////////////////////////////////////////////////////////////////// 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); } /////////////////////////////////////////////////////////////////////// // The nth power of matrix // 1 1 // 1 0 /////////////////////////////////////////////////////////////////////// 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; } /////////////////////////////////////////////////////////////////////// // Calculate the nth item of Fibonacci Series using devide and conquer /////////////////////////////////////////////////////////////////////// long long Fibonacci_Solution3(unsigned int n) { int result[2] = {0, 1}; if(n < 2) return result[n]; Matrix2By2 PowerNMinus2 = MatrixPower(n - 1); return PowerNMinus2.m_00; }
解析
在很多C语言教科书中讲到递归函数的时候,都会用Fibonacci作为例子。因此很多程序员对这道题的递归解法非常熟悉,看到题目就能写出如下的递归求解的代码。
///////////////////////////////////////////////////////////////////////
// Calculate the nth item of Fibonacci Series recursively
///////////////////////////////////////////////////////////////////////
long long Fibonacci_Solution1(unsigned int n)
{
int result[2] = {0, 1};
if(n < 2)
return result[n];
return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
}
但是,教科书上反复用这个题目来讲解递归函数,并不能说明递归解法最适合这道题目。我们以求解f(10)作为例子来分析递归求解的过程。要求得f(10),需要求得f(9)和f(8)。同样,要求得f(9),要先求得f(8)和f(7)……我们用树形结构来表示这种依赖关系
我们不难发现在这棵树中有很多结点会重复的,而且重复的结点数会随着n的增大而急剧增加。这意味这计算量会随着n的增大而急剧增大。事实上,用递归方法计算的时间复杂度是以n的指数的方式递增的。大家可以求Fibonacci的第100项试试,感受一下这样递归会慢到什么程度。在我的机器上,连续运行了一个多小时也没有出来结果。
其实改进的方法并不复杂。上述方法之所以慢是因为重复的计算太多,只要避免重复计算就行了。比如我们可以把已经得到的数列中间项保存起来,如果下次需要计算的时候我们先查找一下,如果前面已经计算过了就不用再次计算了。
更简单的办法是从下往上计算,首先根据f(0)和f(1)算出f(2),在根据f(1)和f(2)算出f(3)……依此类推就可以算出第n项了。很容易理解,这种思路的时间复杂度是O(n)。
///////////////////////////////////////////////////////////////////////
// Calculate the nth item of Fibonacci Series iteratively
///////////////////////////////////////////////////////////////////////
long long Fibonacci_Solution2(unsigned n)
{
int result[2] = {0, 1};
if(n < 2)
return result[n];
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;
}
这还不是最快的方法。下面介绍一种时间复杂度是O(logn)的方法。在介绍这种方法之前,先介绍一个数学公式:
{f(n), f(n-1), f(n-1), f(n-2)} ={1, 1, 1,0}
n-1
(注:{f(n+1), f(n), f(n), f(n-1)}表示一个矩阵。在矩阵中第一行第一列是f(n+1),第一行第二列是f(n),第二行第一列是f(n),第二行第二列是f(n-1)。)
有了这个公式,要求得f(n),我们只需要求得矩阵{1, 1, 1,0}的n-1次方,因为矩阵{1, 1, 1,0}的n-1次方的结果的第一行第一列就是f(n)。这个数学公式用数学归纳法不难证明。感兴趣的朋友不妨自己证明一下。
现在的问题转换为求矩阵{1, 1, 1, 0}的乘方。如果简单第从0开始循环,n次方将需要n次运算,并不比前面的方法要快。但我们可以考虑乘方的如下性质:
要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。如果把求n次方的问题看成一个大问题,把求n/2看成一个较小的问题。这种把大问题分解成一个或多个小问题的思路我们称之为分治法。这样求n次方就只需要logn次运算了。
实现这种方式时,首先需要定义一个2×2的矩阵,并且定义好矩阵的乘法以及乘方运算。当这些运算定义好了之后,剩下的事情就变得非常简单。
转载请注明原文地址:https://kaotiyun.com/show/vRmZ777K
0
程序员面试
相关试题推荐
YourfriendDavidjustsentyouabookthatyouexpectedasabirthdaypresent.Sendane-mailtohimtoexpressyourappreciati
WhenIseeclients,thisisthequestionthatI’maskedthemost.Ifyou’reinapublicplace,lookaround.【F1】Nearlyeveryone
Weakdollarorno,$46,000—thepriceforasingleyearofundergraduateinstructionamidtheredbrickofHarvardYard—is【C1】__
Weakdollarorno,$46,000—thepriceforasingleyearofundergraduateinstructionamidtheredbrickofHarvardYard—is【C1】__
使用.NETPassport向导注册MSN帐户,姓名为李明,邮件的地址为liming@hotmail.com,密码为123456lm。
在金山毒霸2008中,手动查杀“移动存储设备”中的病毒木马。
在Word97的编辑状态,执行“文件”菜单中的“保存”命令后()。A.将所有打开的文档存盘B.只能将当前文档存储在原文件夹的文件内C.可以将当前文档存储在已有的任意文件夹内D.可以先建立一个新文件夹,再将文档存储在该文件夹内
Word的样式是一组巳命名的字符和()格式的组合。
在数据库系统中,“事务”是访问数据库并可能更新各种数据项的一个程序执行单元。为了保证数据完整性,要求数据库系统维护事务的原子性、一致性、隔离性和持久性。针对事务的这4种特性,考虑以下的架构设计场景:假设在某一个时刻只有一个活动的事务,为了保证事务
对计算机评价的主要性能指标有时钟频率、①、运算精度和内存容量等。对数据库管理系统评价的主要性能指标有②、数据库所允许的索引数量和最大并发事务处理能力等。①处应填入?
随机试题
A.自身免疫性溶血性贫血B.地中海贫血C.红细胞G-6PD缺乏性溶血性贫血D.遗传性球形红细胞增多症E.再生障碍性贫血慢性溶血性贫血,黄疸,脾大,红细胞渗透脆性试验(+)
(系统设计中的)经济性原则
CallableStatement对象为所有的DBMS提供了一种以标准形式调用_______的方法。
以下室内给水方式中,不适用于气压给水和微机控制变频调速给水的是()
某公司销售商品均采用赊销方式,预计的年度赊销收入为5000万元,信用条件是(3/10,2/20,N/45),其变动成本率为40%,资本成本率为10%,收账费用为120万元。预计占赊销额60%的客户会利用3%的现金折扣,占赊销额18%的客户会利用2%的现金折
伴随着国内房地产和基建市场规模的逐步扩大,以SBS/APP改性沥青卷材为主导的新型建筑防水材料市场在未来仍有较大的增长空间。但由于该行业技术和资金壁垒低,使得行业集中度很低,前10家企业销售占比不到10%。激烈的市场竞争也造成企业难以进一步提升毛利率,业绩
全党和全社会都要坚持尊重劳动、尊重知识、尊重人才、尊重创造的重大方针。劳动、知识、人才、创造,四者是一个具有内在联系的统一整体,其中居于核心和基础地位的是()
设z=z(x,y)是由9x2一54xy+90y2一6yz—z2+18=0确定的函数,求z=z(x,y)一阶偏导数与驻点;
Completetheformbelow.WriteNOMORETHANTWOWORDSAND/ORANUMBERforeachanswer.
WhatpositionwillWongapplyfor?WhatdidWongdobeforeshewasexternalvice-presidentofChineseUniversitySocietyofBus
最新回复
(
0
)