斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)

时间:2022-12-05 17:39:32
对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - ) + F(n - ),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n)。第一个斐波拉契数为F() = 。 给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 。 

斐波拉契数列的计算是一个非常经典的问题,对于小规模的n,很容易用递归的方式来获取,对于稍微大一点的n,为了避免递归调用的开销,可以用动态规划的思想轻松获得,时间复杂度为O(n),空间复杂度为O(1). 但是对于更大规模,比如上题中的n的范围,动态规划所花的时间也不少了。好在之前在Code Hunt上碰倒这个问题。

考虑下面三个矩阵:

F(n)   F(n-1)        1,1         F(n-1)  F(n-2)

F(n-1) F(n-1)  与   1,0   与   F(n-2)  F(n-3)

分别设为S(n), M, S(n-1).  S(n) = M x S(n-1).

于是

S(n) = M^(n-1) x S(1) = M^n;   (关系1)

再来看看,若n为32位正整数,设c[32]为其二进制序列的逆序列, c[i] =0,1;

n = Σ(c[i]*2^i),  i=0,...,31;

所以只要我知道M的2^i 方幂(i=0,1,2,...,31),我们可以轻松计算出S(n)

而计算出32个M的幂需要做32次矩阵乘法,而计算M^n次方,即M^( Σ(c[i]*2^i) ) 也最多需要做32次矩阵乘法

因而最多64次矩阵乘法即可计算出任意32位正整数范围的n对应的S(n)

 class Fibonacci {
/*author: Haibin Chen*/
public:
int getNthNumber(int n) {
// write code here
if(n <=) return ;
long a[];
long b[];
long c[];
long d[];
a[]=;
b[]=;
c[]=;
d[]=;
int i,j;
for(i=;i<;i++){
a[i] = a[i-];
b[i] = b[i-];
c[i] = c[i-];
d[i] = d[i-];
getMulti(a[i],b[i],c[i],d[i],a[i],b[i],c[i],d[i]);
}
long ra = ,rb =,rc=,rd=,mask=;
for(i=;i<;i++){
if((n&mask)!=){
getMulti(ra,rb,rc,rd,a[i],b[i],c[i],d[i]);
}
mask = mask <<;
}
return ra;
}
void getMulti(long &a,long &b,long &c,long &d,long a1,long b1,long c1,long d1){
long tempa = (a*a1+b*c1)%;
long tempb = (a*b1+b*d1)%;
long tempc = (c*a1+d*c1)%;
long tempd = (c*b1+d*d1)%;
a = tempa;
b = tempb;
c = tempc;
d = tempd;
}
};

斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)的更多相关文章

  1. 剑指offer-第二章算法之斐波拉契数列(青蛙跳台阶)

    递归与循环 递归:在一个函数的内部调用这个函数. 本质:把一个问题分解为两个,或者多个小问题(多个小问题相互重叠的部分,会存在重复的计算) 优点:简洁,易于实现. 缺点:时间和空间消耗严重,如果递归调 ...

  2. 剑指offer-面试题9&period;斐波拉契数列

    题目一:写一个函数,输入n,求斐波拉契数列的第n项. 斐波拉契数列的定义如下: { n=; f(n)={ n=; { f(n-)+f(n-) n>; 斐波拉契问题很明显我们会想到用递归来解决: ...

  3. 剑指offer三&colon; 斐波拉契数列

    斐波拉契数列是指这样一个数列: F(1)=1; F(2)=1; F(n)=F(n-1)+F(n); public class Solution { public int Fibonacci(int n ...

  4. 关于斐波拉契数列(Fibonacci)

    斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10 ...

  5. C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)

    本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...

  6. &lbrack;NEUQ-OJ&rsqb; 1012&Tab;SZ斐波拉契数列

    一道水题,让我看清基础我的基础是多么薄弱. 递归,数组清零,数组名/变量名重复层出不穷...路漫漫啊.......... http://ncc.neuq.edu.cn/oj/problem.php?i ...

  7. 浅谈C&num;中的斐波拉契数列

    突然对那些有趣的数学类知识感兴趣了,然后就简单研究了一下斐波拉契数列,看看它的有趣之处! 斐波拉契数列(Fibonacci Sequence),又称黄金分割数列,该数列由意大利的数学家列奥纳多·斐波那 ...

  8. Go斐波拉契数列&lpar;Fibonacci&rpar;&lpar;多种写法&rpar;

    1 前言 斐波拉契数列有递归写法和尾递归和迭代写法. 2 代码 //recursion func fib(n int) int{ if n < 2{ return n }else{ return ...

  9. python的生成器(斐波拉契数列(Fibonacci))

    代码: 函数版本: #斐波拉契数列(Fibonacci) def fib(max): n=0 a,b=0,1 while n < max: a,b = b,a+b n = n+1 return ...

随机推荐

  1. 理解CSS视觉格式化

    前面的话   CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...

  2. javascript优化--11模式&lpar;设计模式&rpar;02

    策略模式 在选择最佳策略以处理特定任务(上下文)的时候仍然保持相同的接口: //表单验证的例子 var data = { firs_name: "Super", last_name ...

  3. Boostrap学习心得

    进入新公司,前端用到各种页面元素几乎都是bootStrap框架里的,下面介绍下某些页面控件怎么运用,作为知识点备份,提供有需要人观看: 首先下载bootstrap,地址http://www.bootc ...

  4. &lbrack;CSS&rsqb;三角形

    CSS盒子模型 当我们把padding和width,height全部设置为0,border设为一个较大的像素时 即:我们需要什么方向的三角形,只需把其余的三角形背景色设置为transparent:

  5. CUDA学习资料分享&lpar;随时更新&rpar;

    1.Programming_Massively_Parallel_Processors.pdf 2.CUDA_C_Programming_Guide.pdf 3.CUDA范例精解通用GPU编程.pdf ...

  6. H5中input&lbrack;type&equals;&quot&semi;date&quot&semi;&rsqb;默认样式修改 伪类

  7. Java中不定项参数(可变参数)的作用和使用方式

    引言: 我们在编写方法的过程中,可能会遇见一个方法有不确定参数个数的情况.一般我们会用方法重载来解决问题: //方法重载,解决参数个数不确定问题 public void method(); publi ...

  8. APC &vert; Memcache等缓存key冲突的解决的方法

    版权声明:https://github.com/wusuopubupt https://blog.csdn.net/wusuopuBUPT/article/details/24397109 apc.m ...

  9. &lbrack;转&rsqb;&lbrack;CEF&rsqb;自动播放视频

    1.CEF 默认不支持 mp4,可以在网上下载热心网友提供的修改版. 查看支持的特性的方法:在 CEF 中访问网页 :http://html5test.com/ 2. 打开网页后视频自动播放: mut ...

  10. springcloud使用使用Feign-Ribbon做负载均衡实现声明式REST调用

    什么是Feign Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单.使用Feign,只需要创建一个接口并注解.它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解 ...