递归求k阶斐波那契序列的算法?

zhongruanjian 2008-09-12 08:24:15
请教一下,
下面这个程序用递归法实现的求k阶斐波那契序列的第m项的值f,
这个算法用函数递归错在哪里呢?怎么改?
为什么这样写不行啊?
#include<iostream.h>

long fib(long n,long k)
{
if(n<=k)
{
if((n<k-1)||(n>=0))
return 0;
else
if((n==k-1)||(n==k))
return 1;

}
else
return 2*fib(n-1,k)-fib(n-k-1,k);
}
long main()
{
long n,k;
cin>>n>>k;

cout<<"fib("<<n<<","<<k<<")="<<fib(n,k)<<endl;

return 0;
}
分析: k阶斐波那契序列的第m项的值f[m]=f[m-1]+f[m-2]+......+f[m-k]
=f[m-1]+f[m-2]+......+f[m-k]+f[m-k-1]-f[m-k-1]
=2*f[m-1]-f[m-k-1]
所以上述算法的时间复杂度仅为O(m). 如果采用递归设计,将达到O(k^m). 即使采用暂存中间结果的方法,也将达到O(m^2).

...全文
1223 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhongruanjian 2008-11-02
  • 打赏
  • 举报
回复
谢谢提醒.
zhongruanjian 2008-11-02
  • 打赏
  • 举报
回复
多谢拓宽,学妹以后也多多思考.
zhongruanjian 2008-11-02
  • 打赏
  • 举报
回复
谢谢大哥的Java算法 ,小妹正在学Java ,以后多多请教啊
destinyac 2008-10-17
  • 打赏
  • 举报
回复
复杂度是:O(log(k) * n^2 ),n 是n阶,k是第k项。(假设乘法运算是:O(1))

import java.math.BigInteger;
import java.util.*;
/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2008</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/
public class fib {
private static BigInteger a[][] , b[][] ;

/***
* 功能: 矩阵乘法,x = x*y;
* 输入: x, y 为矩阵,n是矩阵的维数:n*n。
* 时间复杂度: O(n^2)
* 空间复杂度: 0(n^2)
*/
private static void mul(BigInteger x[][], BigInteger y[][], int n)
{
BigInteger sum = new BigInteger("0");
BigInteger tmp[][] = new BigInteger[n][n];
for(int i =0 ;i < n ; i ++ ){
for(int j =0 ; j < n ; j ++ ){
sum = BigInteger.ZERO;
for(int k =0 ; k < n ; k ++ ){
sum = sum.add( x[i][k].multiply( y[k][j]) );
}
tmp[i][j] = sum;
}
}
a = tmp;
return ;
}

/***
* 功能: 初始化矩阵a
* 输入: n是矩阵的维数:n*n。
*/
private static void init(int n)
{
a= new BigInteger[n][n];
b = new BigInteger[n][n];
for(int i =0 ; i < n ; i ++ ){
for( int j =0 ; j < n ; j ++ ){
if(i == j+1 ){
a[i][j] = BigInteger.ONE;
}else{
a[i][j] = BigInteger.ZERO;
}
}
a[i][n-1] = BigInteger.ONE;
}
b = a ;
return ;
}

/***
* 功能: 计算n阶斐波那契序列第k项值;
* 输入: n , k 如上。
* 时间复杂度: O( log(k) * n^2 )
* 空间复杂度: 0( n^2 )
*/
private static void fib(int n , int k){
if(k == 1 ) return ;
fib(n,k/2);
mul(a,a,n);
if(1 == k%2 ){
mul(a,b,n);
}
return;
}
public static void main(String args[]) {
Scanner cin = new Scanner(System.in);
while(true){
int n = cin.nextInt(),k = cin.nextInt();
init(n);
fib(n,k);
System.out.println(a[0][n-1]);
}
}
}


计算一个实例:
50 100
316912650057050313499758034944
runfriends 2008-10-16
  • 打赏
  • 举报
回复

class fibonache
{
private unsigned long f;
private unsigned long pref;
unsigned long Fibonache(unsigned long n)
{
f=0;
pref=0;
if (n==1) return f=1;
f=Fibonache(n - 1)+pref;pref=f-pref;
return f;
}
}
runfriends 2008-10-16
  • 打赏
  • 举报
回复


int Fibonache(int i)
{
static int f=0,pref=0;
if (i==1) return f=1;
f=Fibonache(i - 1)+pref;pref=f-pref;
return f;
}
//请版主把我上次回复删了吧。上一个完全错误。这回应该没没问题了。过会去下个TURBO C专门用来验证算法。
mathe 2008-10-16
  • 打赏
  • 举报
回复
一楼的程序显然错了。后面修改后的程序应该没有问题了,只是程序复杂度过高。
不使用递归的代码应该效率可以好一些。
更好的方法是直接使用公式计算(如果只要求浮点结果这个方法更好):
http://zdu.spaces.live.com/blog/cns!C95152CB25EF2037!128.entry
runfriends 2008-10-16
  • 打赏
  • 举报
回复

int Fibonache(int i)
{
static int f=0;
if (i==1) return 1;
return f+=Fibonache(i - 1);
}
currenttt 2008-09-16
  • 打赏
  • 举报
回复
lz是不是结果永远是0?


#include <iostream.h>

long fib(long n,long k)
{
if(n <=k)
{
if((n <k-1)||(n>=0))
return 0;
else
if((n==k-1)||(n==k))
return 1;

}
else
return 2*fib(n-1,k)-fib(n-k-1,k);
}


看了三行,惊奇地发现:

if ( n < k - 1 || n >= 0) return 0;


这里是 || 的话当然不对了……orz
zhongruanjian 2008-09-15
  • 打赏
  • 举报
回复
谢谢赐教, 这个递归应该不是一个无穷递归,你可以输几个数去验证以下。
不知道以下这个我修改了的程序还有那些不足之处,还请多多指教。

#include<iostream.h>
long fib(long n,long k)
{
//long f,a,b;
if(n<k-1)
return 0;
else
if((n==k-1)||(n==k)) //这里把(n==k-1)||(n==k)改成(n=k-1)||(n=k),则在
//n>k+1时,结果都是1。
return 1;
else
{
//a=2*fib((n-1),k);
//b=fib((n-k-1),k);
//f=a-b;
//return f;
return 2*fib((n-1),k)-fib((n-k-1),k); //也可以把被注销的语句恢复,把
//这条语句注销。
}
}
long main()
{
long n,k;

cout<<"n=";
cin>>n;
cout<<"k=";
cin>>k;

cout<<"fib("<<n<<","<<k<<")="<<fib(n,k)<<endl;

return 0;
}
zhongruanjian 2008-09-15
  • 打赏
  • 举报
回复
多谢赐教。
你写的斐波那契序列的求法是对的,可是,那是二阶的。还有一种是更普遍的情况,就是k阶。
问题描述:已知k阶斐波那契序列的定义为
f(0)=0 , f(1)=0 , ... , f(k-2)=0 , f(k-1)=1 ; (k>=2)
f(n)=f(n-1)+f(k-2)+ ... +f(n-k) , n=k,k+1,...
试编写求k阶斐波那契序列的第m项值的函数算法,k和m均以值调用的形式在函数参数表中出现。

不知道以下算法还有什么不足,还请多多纠正。

#include<iostream.h>
long fib(long n,long k)
{
//long f,a,b;
if(n<k-1)
return 0;
else
if((n==k-1)||(n==k)) //这里把(n==k-1)||(n==k)改成(n=k-1)||(n=k),则在
//n>k+1时,结果都是1。
return 1;
else
{
//a=2*fib((n-1),k);
//b=fib((n-k-1),k);
//f=a-b;
//return f;
return 2*fib((n-1),k)-fib((n-k-1),k); //也可以把被注销的语句恢复,把
//这条语句注销。
}
}
long main()
{
long n,k;

cout<<"n=";
cin>>n;
cout<<"k=";
cin>>k;

cout<<"fib("<<n<<","<<k<<")="<<fib(n,k)<<endl;

return 0;
}
ProjectDD 2008-09-15
  • 打赏
  • 举报
回复
 
/// <summary>
/// 非波纳切数列的意思是,后一项的值总是前面两项目之和,并且这个数据有两最初的项值均为1
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
int Fibonache(int i)
{
if (i<=2)
{
return 1;
}
return Fibonache(i - 1) + Fibonache(i - 2);
}
richbirdandy 2008-09-15
  • 打赏
  • 举报
回复
中秋快乐!
lizhaohu 2008-09-15
  • 打赏
  • 举报
回复
f[m]=f[m-1]+f[m-2]+......+f[m-k]
=f[m-1]+f[m-2]+......+f[m-k]+f[m-k-1]-f[m-k-1]
=2*f[m-1]-f[m-k-1] ,这是一个无穷递归呀
jieao111 2008-09-14
  • 打赏
  • 举报
回复
中秋快乐
zhongruanjian 2008-09-14
  • 打赏
  • 举报
回复
http://news.yoeoo.com/a/200808151.html?stra=wuyi8808=zhongruanjian wuyi8808,快看!你上新闻啦,搞笑死了!!
wuyi8808 2008-09-14
  • 打赏
  • 举报
回复
中秋快乐!

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧