在学校的anyview的时候,遇到了这个题:

【题目】已知k阶裴波那契序列的定义为
f(0)=0, f(1)=0, ..., f(k-2)=0, f(k-1)=1;
f(n)=f(n-1)+f(n-2)+...+f(n-k), n=k,k+1,...
试编写求k阶裴波那契序列的第m项值的函数算法,
k和m均以值调用的形式在函数参数表中出现。

要求实现下列函数:
Status Fibonacci(int k, int m, int &f);
/* 如果能求得k阶斐波那契序列的第m项的值f,则返回OK;*/
/* 否则(比如,参数k和m不合理)返回ERROR */

然后我自己想到的是用递归来做,一开始我用的是纯递归,大概思路就是n大于k-1的部分,都用递归解除,然后再把递归的结果累加,最后得到fn。然后提交的时候,虽然出来几个都是right,但速度极慢,可以说是很难跑完。

后来一个大佬帮我看了后,说这里递归好多次,太耗内存了,就好多结果重复算。(因为是累加的时候有很多重复)然后,就改装了一下,弄了个数组来存中间递归的数,来看代码:

/**********
【题目】已知k阶裴波那契序列的定义为
f(0)=0, f(1)=0, ..., f(k-2)=0, f(k-1)=1;
f(n)=f(n-1)+f(n-2)+...+f(n-k), n=k,k+1,...
试编写求k阶裴波那契序列的第m项值的函数算法,
k和m均以值调用的形式在函数参数表中出现。
**********/
int a[]; //数列是拿来记住结果的,不然我这种递归每一次都会很多重复
int beforek = ;
void addCount(int m)
{
for(int i=;i<=m+;i++)
a[i]=; } Status Fibonacci(int k, int m, int &f)
/* 求k阶斐波那契序列的第m项的值f */
{ if(k<=||m<) {
f = ;
return ERROR;
}
if(beforek==||beforek!=k) {
beforek=k;
memset(a,,sizeof(int)*(m+));
}
if(a[m]!=) {f=a[m];return OK;}
if(m<k){
if(m==(k-)){
f = ;
a[m] = f;
return OK;
} else {
f = ;
a[m] = f;
return OK;
}
}
else {//m>=k
int result = ;
int bound = m-k;
m--;
while(m>=bound) {
int temp = ;
Fibonacci(k,m,temp);
a[m] = temp;
result = result + temp;
m--;
}
f = result;
return OK;
}
}

后面有做到这个题,不过是要求用循环队列来做,然后就换个思路思考,

观察发现fn前面k-1个数的取值是0/1,然后fn的值当n大于k-1的时候,
它的值就会等于fn-1还有后面的一共k-1个数的和,所以我们让队列保持有k-1个
数,然后不断插入f,f的值是队列中k-1个数的和,插入后又踢掉一个,直到尾
巴指到n-1,然后再把这个队列末尾那个返回就行了,

看代码:

本题的循环队列的类型定义如下:
typedef struct {
ElemType *base; // 存储空间的基址
int front; // 队头位标
int rear; // 队尾位标,指示队尾元素的下一位置
int maxSize; // 最大长度
} SqQueue;
**********/ /*思路:观察发现fn前面k-1个数的取值是0/1,然后fn的值当n大于k-1的时候,
它的值就会等于fn-1还有后面的一共k-1个数的和,所以我们让队列保持有k-1个
数,然后不断插入f,f的值是队列中k-1个数的和,插入后又踢掉一个,直到尾
巴指到n-1*/ int InitSqQueue(SqQueue &Q,int n) { //初始化,建立空队列
Q.base = (ElemType *)malloc(sizeof(ElemType)*(n+));
if(Q.base==NULL) return ;
Q.front = ;
Q.rear = ;
Q.maxSize = n;
return ;
} int EnSqQueue(SqQueue &Q,ElemType e) {
if( (Q.rear+)%Q.maxSize==Q.front ) {
return ;
} else {
Q.base[Q.rear] = e;
Q.rear = (Q.rear+)%Q.maxSize;
return ;
}
} int DeSqQueue(SqQueue &Q,ElemType &e) {
if(Q.rear==Q.front) {
return ;
} else {
e = Q.base[Q.front];
Q.front = (Q.front+)%Q.maxSize;
return ;
}
} long Fib(int k, int n)
/* 求k阶斐波那契序列的第n+1项fn */
{
if(n<=k-)return ;
if(n==k-)return ;
/*下面的情况n一定是大于k-1的*/
SqQueue Q;
InitSqQueue(Q,n+k);//maxSize应该是无所谓的
int f,i,e;
for(i = ; i <= k- ; i ++) { //结束后循环队列里应该有k个元素
if(i<=k-) {
f = ;
} else if(i==(k-)) {
f = ;
}
EnSqQueue(Q,f);
}
int theRear = k-;//此时的rear元素是k-1
while(theRear <= n-) {
for(i = Q.front, f = ; i < Q.rear; i = (i+)%Q.maxSize) {
f = f + Q.base[i]; //求出的f是队列中k-1个元素的和
}
EnSqQueue(Q,f);//f入队
DeSqQueue(Q,e);//出一个队,保持队列中有k-1个元素
theRear++;
}
return Q.base[Q.rear-];//最后一个就是fn的值
}

关于k阶裴波那契序列的两种解法的更多相关文章

  1. 【严蔚敏】【数据结构题集(C语言版)】1.17 求k阶斐波那契序列的第m项值的函数算法

    已知k阶斐波那契序列的定义为 f(0)=0,f(1)=0,...f(k-2)=0,f(k-1)=1; f(n)=f(n-1)+f(n-2)+...+f(n-k),n=k,k+1,... 试编写求k阶斐 ...

  2. k阶斐波那契数列fibonacci第n项求值

    已知K阶斐波那契数列定义为:f0 = 0,  f1 = 0, … , fk-2 = 0, fk-1 = 1;fn = fn-1 + fn-2 + … + fn-k , n = k , k + 1, … ...

  3. K阶斐波那契数列--------西工大NOJ习题.10

    K阶斐波那契数列--------西工大NOJ习题.10 原创不易,转载请说明出处!!! 科普:k阶斐波那契数列的0到n-1项需要有初始值. 其中,0到n-2项初始化为0,第n-1项初始化为1. 在这道 ...

  4. 斐波那契数列 的两种实现方式(Java)

    import java.util.Scanner; /* 斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 如果设F(n)为该数列的第n ...

  5. [算法基础]斐波那契(recursion+loop)两种方式执行时间对比

    一.斐波那契数列求第n项两种方式 1.递归(自上而下)def recur_fibonacci(n): if n <= 0: return 0 if n == 1: return 1 return ...

  6. 爬楼梯问题-斐波那契序列的应用.md

    N 阶楼梯,一次可以爬1.2.3...n步,求爬楼梯的种类数 /** * 斐波那契序列 */ public class ClimbingStairs { // Sol 1: 递归 // 递归 公式:F ...

  7. 裴波那契查找详解 - Python实现

    裴波那契查找(Fibonacci Search)是利用黄金分割原理实现的查找方法. 斐波那契查找的核心是: 1.当key == a[mid]时,查找成功: 2.当key < a[mid]时,新的 ...

  8. 最长斐波那契序列-LeetCode-873

    英文版A sequence X_1, X_2, ..., X_n is fibonacci-like if: - n >= 3- X_i + X_{i+1} = X_{i+2} for all ...

  9. 浅谈矩阵加速——以时间复杂度为O(log n)的算法实现裴波那契数列第n项及前n之和使用矩阵加速法的优化求法

    首先请连矩阵乘法乘法都还没有了解的同学简单看一下这篇博客: https://blog.csdn.net/weixin_44049566/article/details/88945949 首先直接暴力求 ...

随机推荐

  1. CxImage的编译及简单使用举例

    1.  从http://sourceforge.net/projects/cximage/下载最新的CxImage 702源代码. 2.  解压缩后,以管理员身份打开CxImageFull_vc10. ...

  2. poj 1426 Find The Multiple ( BFS+同余模定理)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18390   Accepted: 744 ...

  3. ecshop广告宽度值必须在1到1024之间的解决方法

    ecshop加广告出现广告位的宽度值必须在1到1024之间的解决方法,这个问题是今天刚刚发现的,我就郁闷了,如今1024宽度的广告能做什么.你看看京东,天猫,非常多都是大型的横幅广告,这点ecshop ...

  4. 阿里云cenos 6.5 模板上安装 docker

    本章将介绍在阿里云的 Centos6.5 模板上安装 Docker 以及在 Ubuntu 14.04 模板上安装 Docker 的过程 Centos 6.5 模板上使用Docker 首先,通过 ssh ...

  5. 2014/4/18 ① button与submit的区别 ②现象 : 数据库中其他值可以取到 有的却取不到 解决 看获取时“#”有无

    ①<input type="button" /> 这就是一个按钮.如果你不写javascript 的话,按下去什么也不会 发生. <input type=&quo ...

  6. 装饰器的初识,基于bootstrap的前端开发

    1装饰器的初识 概念:不改变函数原来的调用方式,动态地给函数添加功能 开放封闭的原则:1>对添加的新功能是开放的,32>不要在元代码进行修改(封闭) 1.1>函数的定义:对代码块和功 ...

  7. UPDATE command denied DELETE

    可用磁盘空间不足 支持SELECT information_schema. TABLES

  8. rip是典型的距离矢量动态路由协议。Ospf是链路状态型的协议

    网络工程师十个常见面试问题-看准网 https://m.kanzhun.com/k-mianshiwenti/1465113.html 两者都属于IGP协议,rip是典型的距离矢量动态路由协议.Osp ...

  9. BAPI 关闭和删除PR

    当PR在SAP里面已不再使用时,可使用批量使用以下两个BAPI进行处理: BAPI_REQUISITION_DELETE,进行删除处理, (速度快) BAPI_PR_CHANGE,进行关闭,但不删除( ...

  10. 单点登录原理及实现sso

    WEB的登录那些事 说道账户登录和注册,其实我们每天都在亲身感受着,像微博.知乎还有简书等等.我们总是需要定期的去重新登录一下,对于这种认证机制,我们都能说出来两个名词,Cookie.Session. ...