笔试题解答(个人水平有限,有错误之处请指出)
来源:互联网 发布:淘宝大学生创业 编辑:程序博客网 时间:2024/04/29 11:12
斐波那契数列的每一项f(n),计算出f(n)<int所能表示的最大值的n值为多少?
刚开到这道题,哇,太简单了吧,有个递归就可以搞定斐波那契数列啦,于是写了一个简单的递归实现的斐波那契数列算法:
int fib(int n)
{
if(n==1||n==2)
{
return 1;
}
else
{
return fib(n-1)+fib(n-2);
}
}
试着运行了一下,当n的值大于40时,运行速度就慢了很多了,试想一下距离int所能表示的最大值2^31-1还远着呢,看来用递归是不可行的。
接下来想了想,既然递归能够实现,那循环肯定也是实现斐波那契数列的啦~~
int f1(int n)
{
int a = 1;
int b = 1;
double k =double(n);
int j =ceil(k/2); //天花板函数,算出所要求的项的二分之一的上值
for(int i=1;i<= j-1;i++)
{
a += b;
b += a;
}
if(n%2==0)
return b;
else
return a;
}
果然不出所料,循环实现的这个算法比递归真的要快上N倍,而且n值能够取得最大值是依赖于int能够表示的范围的,超出了int表示范围就变成负数了。n=46时,是int能够表示的最大的斐波那契值了。
其实这道题用循环就可以解出来了,不过对于运行速度还是有要求的话,我们就可以直接用斐波那契数列的通项公式算出具体的某个值。通项为F(n)=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}(√5表示根号5)
int f2(int n)
{
return (pow((1+sqrt(5.0))/2,n)-pow((1-sqrt(5.0))/2,n))/sqrt(5.0);
}
这个算法当然就更快了,都不用递归或循环,只要输入一个n值就可以直接算出来了,数学公式果然是强大的解题工具。
这道题的解题过程如下:
int f2(int n)
{
return (pow((1+sqrt(5.0))/2,n)-pow((1-sqrt(5.0))/2,n))/sqrt(5.0);
}
int main()
{
int n=1;
int max = pow(2,31)-1;
while(f2(n)<max&&f2(n)>0)
{
n++;
}
cout<<n-1<<endl;
return 0;
}
结果n=46
现在算一下这几个算法运行的时间长短:
在网上搜了个比较精确的计数器程序:
double getTime2() //使用高精度计时器
{
static LARGE_INTEGER s_freq;
LARGE_INTEGER performanceCount;
double t;
if (s_freq.QuadPart==0)
{
if ( !QueryPerformanceFrequency( &s_freq))
return 0;
}
QueryPerformanceCounter( &performanceCount );
t=(double)performanceCount.QuadPart / (double)s_freq.QuadPart;
return t;
}
测量程序如下:
int main()
{
double t1=getTime2();
fib(35); //再大的话程序就卡在那里了,所以选了个35,跟其他两个算法不一样
double t2=getTime2();
cout<<"fib(n)递归:"<<t2-t1<<endl;
double t3=getTime2();
f1(46);
double t4=getTime2();
cout<<"f1(n)循环:"<<t4-t3<<endl;
double t5=getTime2();
f2(46);
double t6=getTime2();
cout<<"f2(n)公式:"<<t6-t5<<endl;
return 0;
}
运行结果如下:
fib(n)递归:0.722634
f1(n)循环:7.82222e-006
f2(n)公式:3.35238e-006
从上面的运行时间可以看出来,递归实在是太慢了,公式法的速度优于循环,不过循环也比递归快很多了,都不是一个数量级的差别了~~
- 笔试题解答(个人水平有限,有错误之处请指出)
- drupal7中的用户添加于更新(完全个人开发所得,如有不妥之处请大虾指出)
- I/O多路复用之select()简要总结分析一(错误之处请指出)
- Performance vs. load vs. stress testing _Grig Gheorghiu (翻译水平有限,如有错误请帮忙刊正)
- 关于Java的二进制输入输出流的一点总结(有错误请指出)
- Android(实习生)第一次面试总结,如有回答错误还请大家指出来哦~
- sdl学习心的(有错误请指出)
- 在MFC中生成数据源过程中所遇到的问题及解决(如有错误,请指出)
- 渲染流水线的工作过程——个人理解,有问题请指出
- 写了些JS扩展,有错误请指出,希望对大家有用^^
- 写了些JS扩展,有错误请指出,希望对大家有用^^
- 输出ASCII中的最大值的代码,有错误地方还请指出
- 整理自己所学java基础内容,有错误的请大家指出,相互进步
- 请检查如下代码,如有问题,请正确指出!(java、多线程)
- 搜狗2013校园招聘java笔试题分析(个人的一点分析拙见,不到之处请不吝赐教)
- 开发游戏里做的一个背包数据分页,有不足处请指出
- 21天学会c++(英汉对照,个人翻译,水平有限,供参考)-------第2天
- struts2执行流程(个人理解,有错误请批评指正)
- 黑客是怎样“挂马”的
- 关于vs 2008字符集问题
- Lucene.Net 2.3.1开发介绍
- C#操作Cookie注意事项
- SSAS : 使用.NET为SSAS编写自定义程序集
- 笔试题解答(个人水平有限,有错误之处请指出)
- 图片与二进制流的转化
- 什么是GDI
- oracle数据类型
- 显示中文的小例子 qt4 (补充)
- Windows 32操作系统中虚拟内存的性能设置(sql)
- [双语阅读]调查:美国高管冷落社交网络
- 8 张思维导图学习 Javascript —— javascript运算符
- 怀念 The king of pop -- 迈克尔·杰克逊(MichaelJackson)