一道面试题:如何判断一个整数是否是fibonacci数列中的数?

mengxiang2003 2007-08-23 10:03:16
rt!
fibonacci数列指的是这样一个数列:1,1,2,3,5,8,13,21……
...全文
6745 66 打赏 收藏 转发到动态 举报
写回复
用AI写文章
66 条回复
切换为时间正序
请发表友善的回复…
发表回复
raibow 2010-09-15
  • 打赏
  • 举报
回复
2楼的程序for循环i应该从1开始就对了。
lyonslch 2008-03-14
  • 打赏
  • 举报
回复
递归和非递归哪个更省时啊?我需要一个更快的,用递归好慢,最后直接得等近五分钟啊
Cherish20 2007-08-29
  • 打赏
  • 举报
回复
好久没有写算法方面的东西了,感觉自己已经落伍了。
继续学习。呵
houdy 2007-08-27
  • 打赏
  • 举报
回复
呵呵,作为一个面试题,使用查表的方法不失一个"聪明"的回答,最起码可以说明你比较灵活:)
KISS -- Keep It Simple, Stupid
mLee79 2007-08-27
  • 打赏
  • 举报
回复
拷贝应该没啥问题, 一般的编译器这个应该会做 NRV , 很少研究大数算法, 一般就用用 openssl , 这个只是因为 openssl 对付 10M 以上的Fib数太慢才临时改的, 只是说明下算法 ...

计算下 Fib( N = ||( log( sqrt(5) ) + log( XX ) ) / log( (1+sqrt(5))/2 )|| ) 是否与 XX 相等就可以了 .....
iambic 2007-08-27
  • 打赏
  • 举报
回复
>>线形递增
“线性递增”的复杂度是什么意思?不会是O(n)吧。
gxqcn 2007-08-27
  • 打赏
  • 举报
回复
上述程序慢,是因为如下原因:
1、getFibN() 函数若直接调用内部函数“return CHugeIntX().Fibonacci( N );”,将会快很多;
2、getFibN() 函数返回定义不好,存在一个潜在拷贝过程,最好是返回一个引用。
mLee79 2007-08-27
  • 打赏
  • 举报
回复
搞个最简单的, 不适合N很大(比如第50M附近的fib数)的情况, 这种特别大的数,应该首先验证下比如 首100位末100位以及随机的中间的100位 然后在进行完全的验证 ....
大数库用的 gxqcn(★) HugeCalc ← http://hugecalc.ik8.com/ , 不过貌似用的版本很低, 嘻嘻, 速度不是很快 ....

#include <iostream>
#include <hugecalc/HugeIntX.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;

typedef unsigned int ul;
static const ul prevFN [] = {
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,
6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,
832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,
102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073 };
class FNum
{
public:
CHugeIntX getFibN ( ul N ) {
if( N < sizeof( prevFN ) / sizeof( prevFN[0] ) - 5 )
return CHugeIntX( prevFN[N] );
unsigned bits ;
for( bits = 31; bits ; --bits ) if( N&(1<<bits) ) break;
CHugeIntX X1 ( 1 ) , X2 ( 1 ) , X3 , R1 , R2 ;
if( N & 1 ) R1 = R2 = CHugeIntX(1);
for( unsigned i = 1; i <= bits ; ++i ){
X3 = (X1*X1+5*X2*X2); X3>>=1;
X2 = (X1*X2); X1.Swap( X3 );
if( !(N&(1<<i)) ) continue;
if( !R1 ) { R1 = X1 ; R2 = X2 ; continue; }
X3 = ( R1 * X1 + 5 * R2 * X2 ) ; X3 >>= 1;
R2 = ( R1 * X2 + R2 * X1 ) ; R2 >>= 1;
R1.Swap( X3 ); }
return R2; }
bool isFNum( const CHugeIntX& x ) {
if( x < 0 )
return false;
else if( x <= prevFN[ sizeof( prevFN ) / sizeof( prevFN[0] ) - 1 ] )
return isSmallFNum( x );
else // if( x.GetBits() <= 400 )
return isFNum_1( x );
//else
// return isFNum_X( x );
}
private:
bool isSmallFNum( const CHugeIntX& x ){
return binary_search( prevFN , prevFN+sizeof(prevFN)/sizeof(prevFN[0]) , x ); }
bool isFNum_1( const CHugeIntX& x );
bool isFNum_X( const CHugeIntX& x );
};

bool FNum::isFNum_1( const CHugeIntX& x )
{
static const double l2 = .69314718055994529 , ls5 = .80471895621705025 , lfl = .48121182505960347;
unsigned bits = x.GetBits() , N;
CHugeIntX CP(x); CP >>= bits - 15;
N = (unsigned)( .5 + ( ls5 + (bits-15) * l2 + log( (double)(unsigned)CP ) ) / lfl );
return x == getFibN( N ) ? true : false;
}



int main()
{
FNum foo;
CHugeIntX X ( foo.getFibN( 6000000 ) );
cout << foo.isFNum( X ) << endl;

cout << foo.isFNum( X - 1 ) << endl;
cout << foo.isFNum( X + 1 ) << endl;

cin.get();
return 0;
}
DLMU_net 2007-08-26
  • 打赏
  • 举报
回复
mengxiang2003(blog.sina.com.cn/fantasyfly) ( ) 信誉:99 2007-8-25 10:28:07 得分: 0



DLMU_net(张力) 说说你的解法啊,其实当时面试官也说这个题其实很简单的,比后面那个写strstr还要简单。应该有很简单的解法。

------------------------------------恢复楼主,出题人的意图并不是在大整数运算,我写的代码如下:
#include<iostream>
using namespace std;
int main(void)
{
unsigned int value;
unsigned int a[2];
cin>>value;
a[0]=1;a[1]=1;
while(1){
if(value == a[0] || value == a[1]){
cout<<value<<"is a fabonacci num"<<endl;
break;
}
if(value < a[1] && value > a[0]){
cout<<value<<"is not a fabonacci num"<<endl;
break;
}
unsigned int temp=a[0];
a[0]=a[1];
a[1]=a[1]+temp;
}
system("pause");
return 0;
}


LineAge_Hell 2007-08-26
  • 打赏
  • 举报
回复
线形递增
iambic 2007-08-26
  • 打赏
  • 举报
回复
那请问楼上的兄弟,你的算法复杂度是多少啊?

另外大整数问题实在不值得操心,也没必要自己实现。
LineAge_Hell 2007-08-26
  • 打赏
  • 举报
回复
我之所以不想说,是因为用到了很多的数学,汇编,正则表达式的知识,说起来很麻烦,牵扯到很多证明与推理,并非是觉得自己很怎么样,希望各位兄弟不要误会
LineAge_Hell 2007-08-26
  • 打赏
  • 举报
回复
1.数字的在内存中的宽度
假如说是第1M个数字,那么除了特殊的编译器,否则没有适合的数据类型可以容纳那么大的数,你可以用N个字节(8位)来表示这个数字(因为是正整数,所以不必考虑符号位),为了方便的话,你大可以用16进制来表示(其实这样是比较好的表示方法,用来计算也简单).这样就不必担心范围的问题,因为N是自己指定的,所以他可以随意大.
2.通项公式的变形与数学的联系
通项公式(不用手工,而是用计算机计算)的计算结果一定是有误差的,所以是不准确的,那么通过变形,是可以用的,思想是这样的,把他展开,消除根号,里面的式子通过观察是一个
(a+b)^n - (a+(-b))^n 的形式,是有一半的项是可以消除的,那么利用杨辉三角,将其展开,可以得到一个多项式,那么根据这个多项式,就可以得出结果了
iambic 2007-08-26
  • 打赏
  • 举报
回复
to LineAge_Hell:
你要是有炫耀的资本,拿出来炫耀下也是很好的啊。
heibing578604041 2007-08-26
  • 打赏
  • 举报
回复
楼上的观点我赞同,我曾写过一个程序证明了这个观点,确实是越来越接近0。618
LineAge_Hell 2007-08-25
  • 打赏
  • 举报
回复
你们的解决方法太有思想的局限性了,你们把自己的思想局限在程序中了,或者是数学中了,用通项公式是算不出来的,别忘了浮点数在内存中的表示,试着用数学加程序,你会得到意想不到的收获,我不打算把解法发出来,如果发出来的话有炫耀的嫌疑,呵呵,想要的话,
xklee_world@hotmail.com
LineAge_Hell 2007-08-25
  • 打赏
  • 举报
回复
下周我给你一个完美解法
LZLearning 2007-08-25
  • 打赏
  • 举报
回复
2楼的方法好!
hcy830527 2007-08-25
  • 打赏
  • 举报
回复
新手,写一个练练
bool IsFibonacci(int nInput)
{
if (nInput == 1)
{
return true;
}
else
{
int nPre = 1;
int nBack = 1;
int nCheck = 1;
while (nCheck < nInput)
{
nCheck = nBack + nPre;
if (nCheck == nInput)
{
return true;
}
nPre = nBack;
nBack = nCheck;
}
}
return false;
}
let_off 2007-08-25
  • 打赏
  • 举报
回复
比较支持查表,一劳永逸的事,查表效率也可以通过某些途径提高的,这也是空间和时间的一种选择
加载更多回复(46)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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