Fibonacci 数列O(logn)解法
传统解法
提到斐波那契数列(Fibonacci Sequence),首先想到的是经典的动规(DP)算法。
时间复杂度O(n),这里空间复杂度可以优化到O(1)。代码如下:
int fib_n(int n)
{
int dp[] = {, };
if (n <= ) return dp[n]; for (int i = ; i <= n; ++i)
dp[i % ] = dp[(i - ) % ] + dp[(i - ) % ]; return dp[n % ];
}
但是初次接触O(logn)解法有如醍醐灌顶,叹为观止……
O(logn)解法
思路来源 1
考虑一个求幂运算。比如求an,一般来说需要n次累乘,时间复杂度显然是O(n)。实际上可以通过递归达到一种更优化的效果:
an = (an/2)2 * an%2
这里的n/2是取整,如5/2=2。这样就可以实现相当于二分的效果,时间复杂度为O(logn)。
思路来源2
对于Fib数列an(n ≥ 0),可以通过矩阵乘法的方式进行递推:

进而可以得到:

这样就(很机智地)把Fib数列问题转化成了一个求矩阵幂的运算。
解题方法
结合以上思路,首先将其转化为矩阵求幂问题,然后进行二分,O(logn)解法由此诞生。再次感慨人类清奇的脑洞 _(:з」∠)_
以下是代码:
int** mult(int** m1, int** m2)
{
int** res = new int*[];
for (int i = ; i < ; ++i) res[i] = new int[]; res[][] = m1[][] * m2[][] + m1[][] * m2[][];
res[][] = m1[][] * m2[][] + m1[][] * m2[][];
res[][] = m1[][] * m2[][] + m1[][] * m2[][];
res[][] = m1[][] * m2[][] + m1[][] * m2[][]; return res;
} int** recur(int x)
{
if (x == ) {
int** res = new int*[];
for (int i = ; i < ; ++i) res[i] = new int[];
res[][] = res[][] = ;
res[][] = res[][] = ;
return res;
}
if (x == ) {
int** res = new int*[];
for (int i = ; i < ; ++i) res[i] = new int[];
res[][] = res[][] = res[][] = ;
res[][] = ;
return res;
}
int** half = recur(x / );
return mult(mult(half, half), recur(x % ));
} // time: O(logn)
int fib_logn(int n)
{
if (n == || n == ) return ;
int** mat = recur(n - );
return mat[][] + mat[][];
}
结果比较
简单比较一下后者的优化效果,为了是效果更明显,这里将参数设置成一个较大的数(如109),以下是代码以及结果:
void test()
{
const int num = 1e9;
clock_t t1, t2; t1 = clock();
fib_n(num);
t2 = clock();
printf("O(n): %.4f s\n", (double)(t2 - t1) / CLOCKS_PER_SEC); t1 = clock();
fib_logn(num);
t2 = clock();
printf("O(logn): %.4f s\n", (double)(t2 - t1) / CLOCKS_PER_SEC); }
结果

O(n)算法的速度达到了男子百米的世界顶级水平,而O(logn)只表现出一脸不屑……
好吧,我服……那我把logn的多跑几次 for (int i = ; i < ; ++i) fib_logn(num);

那么结果也很明显了,O(logn)算法表现惊艳!
THE END
Fibonacci 数列O(logn)解法的更多相关文章
- 程序员面试题精选100题(16)-O(logn)求Fibonacci数列[算法]
作者:何海涛 出处:http://zhedahht.blog.163.com/ 题目:定义Fibonacci数列如下: / 0 n=0 f(n)= ...
- Fibonacci数列的解法
Fibonacci数列的解法: 1.递归算法 递归的概念,我说不清楚,语文不好.但是核心思想,我认为就是入栈出栈.比方说,你想要求得某个结果,如果一步求解不出来,那么先把最后一步的计算步骤进栈,先不考 ...
- 《面试题精选》15.O(logn)求Fibonacci数列
题目:定义Fibonacci数列例如以下: / 0 n=0 f(n)= 1 n=1 ...
- 【编程题目】题目:定义 Fibonacci 数列 输入 n,用最快的方法求该数列的第 n 项。
第 19 题(数组.递归):题目:定义 Fibonacci 数列如下:/ 0 n=0f(n)= 1 n=1/ f(n-1)+f(n-2) n=2输入 n,用最快的方法求该数列的第 n 项. 思路:递归 ...
- fibonacci 数列及其应用
fibonacci 数列及其延展 fibonacci计算 fibonacci数列是指 0,1,1,2,3,5,8,13,21……这样自然数序列,即从第3项开始满足f(n)=f(n-1)+f(n-2): ...
- 青蛙跳台阶(Fibonacci数列)
问题 一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级.求该青蛙跳上一个n 级的台阶总共有多少种跳法. 思路 当n=1时,只有一种跳法,及f(1)=1,当n=2时,有两种跳法,及f(2)=2,当n= ...
- 【费式数列(Fibonacci数列)】
/* 说明: Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:若有一只兔子每个月生一只小兔子,一个月后也开 始生产.起初只有一只兔子,一个月后就有两只兔子,二个月后就有三只兔子,三 ...
- 常系数线性递推的第n项及前n项和 (Fibonacci数列,矩阵)
(一)Fibonacci数列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的第n项的快速求法(不考虑高精度). 解法: 考虑1×2的矩阵[f[n-2],f[n-1]].根据fibon ...
- Fibonacci 数列算法分析
/************************************************* * Fibonacci 数列算法分析 ****************************** ...
随机推荐
- Java垃圾回收学习笔记
通常来说,要写Java代码,你基本上都没必要听说垃圾回收这个概念的.这不,对于已经写了5年多Java代码的我来说,我还没有哪次经历说是需要使用垃圾回收方面的知识来解决问题的.但是,我依然督促自己花了几 ...
- java基础:数组的拼接
- android sdk tools 一览
ANDROID SDK ADKROID SDK的工具划分为两部分,一部分是SDK tools,与平台无关,另一部分是Platform tools支持最新的安卓平台 SDK tools有 SDK m ...
- KoaHub平台基于Node.js开发的Koa 连接支付宝插件代码信息详情
KoaHub平台基于Node.js开发的Koa 链接支付宝插件代码信息详情 easy-alipay alipay payment & notification APIs easy-alipay ...
- 1592: [Usaco2008 Feb]Making the Grade 路面修整
1592: [Usaco2008 Feb]Making the Grade 路面修整 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 428 Solv ...
- 1734: [Usaco2005 feb]Aggressive cows 愤怒的牛
1734: [Usaco2005 feb]Aggressive cows 愤怒的牛 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 217 Solved: ...
- CentOS7搭建Confluence Wiki
前言 在艾佳生活实习时,有三款团队协作系统特别喜欢:Wiki.Jira和Jenkins.对于Jenkins的搭建,之前<自动部署工具Jenkins>有过记录.这次,搭建一个Wiki,作为知 ...
- .Net轻量级ORM-NPoco的使用方法-摘自NPoco国外官方Wiki
文章引用自NPoco官方Wiki,地址:https://github.com/schotime/NPoco/wiki,因公司网络不稳定,有时无法访问,特将其摘抄. Home Adam Schroder ...
- Android使用Sugar ORM创建数据库报no such table:...的解决方法
在学习使用Android开源框架Sugar ORM时,只是做了开始的创建数据库的操作就报出如下的异常信息 android.database.sqlite.SQLiteException: no suc ...
- “倔驴”一个h5小游戏的实现和思考(码易直播)——总结与整理
3月23日晚上8点半(中国队火拼韩国的时候),做了一期直播分享.15年做的一个小游戏,把核心代码拿出来,现场讲写了一遍,结果后面翻车了,写错了两个地方,导致运行效果有点问题,直播边说话边写代码还真不一 ...