请登陆或者注册新用户 用户名 密码 记住密码 注册新用户

回 帖 快速回帖 发 新 帖 刷新版面
主题:很多人说用递归法算斐波那契数效率低,我不信!

作者:ggggqqqqihc

专家分:540

级别:3级别:3

发表时间:2008-2-12 16:37:00    [回复] 
楼主
就是很常见的fib(1)=1, fib(2)=1, fib(n)=fib(n-1)+fib(n-2)
我当然不是按着一般的书上写的。

#include <stdio.h>
int fib(int n, int a, int b, int count){
    if (count==n){
        return b;
    }
    return fib(n, b, a+b, count+1);
}
int main(){
    int n;
    scanf("%d",&n);
    int s=fib(n,0,1,1);/* 计算第n项 */
    printf("%d\n",s);
    return 0;
}



而一般书上是这样写的:

int fib(int n){
  if (n==1||n==2)
    return 1;
  else
    return fib(n-1)+fib(n-2);
}

  最后修改于2008-2-12 16:54:00

 

签名档
我的Blog

Python好,Python妙,Python代码呱呱叫。

作者:justforfun626

专家分:18460

级别:93级别:93级别:93级别:93级别:93级别:93级别:93级别:93

发表时间:2008-2-13 14:49:00    [回复]  [引用]
21楼
To SonicLing

Where did I need max(n)?

Will you please shut-up your garbage???

Thanks!

PS. I will stop arguing on this thread, it is just wasting my time to argue with people who know-nothing but pretend knowing everything...

I quit!




  最后修改于2008-2-13 14:56:00

作者:rickone

专家分:15390

级别:77级别:77级别:77级别:77

发表时间:2008-2-13 14:56:00    [回复]  [引用]
22楼
我试过了,你满意了

n=1000000,就可以把内存吃得卡不动了,1分多钟没有反应;这不是语言的问题。

 

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-13 14:59:00    [回复]  [引用]
23楼
引用
To SonicLing

Where did I need max(n)?

Will you please shut-up your garbage???

Thanks!

PS. I will stop arguing on this thread, it is just wasting my time to argue with people who know-nothing but pretend knowing everything...

I quit!




garbage??? 你真的认为ruby解释器可以把地球都包进去吗?就算能,还有整个宇宙呢。

 

作者:justforfun626

专家分:18460

级别:93级别:93级别:93级别:93级别:93级别:93级别:93级别:93

发表时间:2008-2-13 15:05:00    [回复]  [引用]
24楼
引用
我试过了,你满意了

n=1000000,就可以把内存吃得卡不动了,1分多钟没有反应;这不是语言的问题。



Very good! Thanks a lot!!!!

Yes, of course, that is expectable. That was just an exercise of mine for playing rubyquiz code.

In the real world, we use different method to solve different problem.

Nobody needs to do fib in your job, if you really need, call a math library.

You call math library to solve most existing algorithm problems. 

What we really need is to solve real world problem which has not been on the textbook or PHD disertation yet. That is where the money is.




  最后修改于2008-2-13 15:23:00

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-13 15:13:00    [回复]  [引用]
25楼
没什么。F数列大数计算使用矩阵法,O(logn)的时间复杂度,O(1)的空间复杂度,算是比较可以接受了。

实在是天文数字,就对n进行划分,然后并行计算。

与ruby无关。

 

作者:rickone

专家分:15390

级别:77级别:77级别:77级别:77

发表时间:2008-2-13 15:22:00    [回复]  [引用]
26楼
这下真相大白了。

 

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-13 15:27:00    [回复]  [引用]
27楼
引用

Nobody needs to do fib in your job, if you really need, call a math library.


总算说了句实话。

这个帖子就是讨论效率问题。没人说你的代码garbage,也没人说ruby garbage,也没人敢说你garbage。不要遇到一丁点问题就garbage garbage乱叫。难道跟你意见不一致的都叫garbage?你一开始就把你的对手定位为garbage,那还用讨论个啥?我们这些所谓的“garbage”都来听你讲课好了,你说是1就是1,是2就是2,没啥好讨论了。

 

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-13 15:40:00    [回复]  [引用]
28楼
本人不喜欢Java、C#,就是因为他们的东西都是不需要讨论的,不可能被misinterpreted,是这样就使这样,是那样就是那样。Java、C#区大多都是死气沉沉的,要么就是那些不知道是不是牛人的牛人们照本宣科贴些东西。

在C/C++区讨论就要尊重对手,因为初学的人也能发现深刻的问题。不管你理解的对不对,各种观点拿出来平等的晒一晒,辩一辩,这样对所有参与的人都有好处。恶毒的攻击对谁都没好处。一来,你说服别人的目的没达到,二来,只能激起更大的反抗。

 

作者:MasterRaySoul

专家分:2830

级别:15级别:15级别:15级别:15级别:15级别:15

发表时间:2008-2-13 15:49:00    [回复]  [引用]
29楼
Ruby 没用过,对它的语法什么的就不敢评论

有没有人注意到我在10楼所回复的?再贴一遍
分成两个接近的数(差1),近似于二分计算

#include <stdio.h>

unsigned long long fib[200]={0, 1, 1};

unsigned long long Fibonacci(unsigned n)
{
    unsigned a, b;
    if (fib[n]) return fib[n];
    b = (a=n>>1) + (n&1);
    return fib[n]=Fibonacci(a)*Fibonacci(b-1) + Fibonacci(a+1)*Fibonacci(b);
}

int main(void)
{
    unsigned n;
    scanf("%u", &n);
    printf("%llu\n", Fibonacci(n));
    return 0;
}

 

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-13 16:01:00    [回复]  [引用]
30楼
生成数组的复杂度O(logn),平均复杂度O(1),空间复杂度O(max(n))

空间换时间一般要准备N的上限的空间,所以空间复杂度是O(max(n))

如果采用动态大小的空间,该算法的空间复杂度可以降低为O(logn),但是时间复杂度就不再是O(1),而是动态空间的维护算法复杂度+O(1)

fun采用了Ruby的动态性,如果考虑这一点的话,空间复杂度是O(n),但是时间复杂度会相应增加,如同楼主在前面所指出。(PS:这算是对Where did I need max(n)?的回答。)

  最后修改于2008-2-13 16:10:00

作者:w1212q

专家分:660

级别:4级别:4级别:4

发表时间:2008-2-14 0:10:00    [回复]  [引用]
31楼
如果计算机计算1+1得出的结果是3,那么你们的算法就全错了

 

作者:rickone

专家分:15390

级别:77级别:77级别:77级别:77

发表时间:2008-2-14 2:29:00    [回复]  [引用]
32楼
引用
#include <stdio.h>

unsigned long long fib[200]={0, 1, 1};

unsigned long long Fibonacci(unsigned n)
{
    unsigned a, b;
    if (fib[n]) return fib[n];
    b = (a=n>>1) + (n&1);
    return fib[n]=Fibonacci(a)*Fibonacci(b-1) + Fibonacci(a+1)*Fibonacci(b);
}

int main(void)
{
    unsigned n;
    scanf("%u", &n);
    printf("%llu\n", Fibonacci(n));
    return 0;
}


这个方法是正确的吗?

 

作者:MasterRaySoul

专家分:2830

级别:15级别:15级别:15级别:15级别:15级别:15

发表时间:2008-2-14 8:38:00    [回复]  [引用]
33楼
测试过很多数据,是正确的。

 

作者:SonicLing

专家分:6260

级别:32级别:32级别:32

发表时间:2008-2-14 13:48:00    [回复]  [引用]
34楼
引用
引用
#include <stdio.h>

unsigned long long fib[200]={0, 1, 1};

unsigned long long Fibonacci(unsigned n)
{
    unsigned a, b;
    if (fib[n]) return fib[n];
    b = (a=n>>1) + (n&1);
    return fib[n]=Fibonacci(a)*Fibonacci(b-1) + Fibonacci(a+1)*Fibonacci(b);
}

int main(void)
{
    unsigned n;
    scanf("%u", &n);
    printf("%llu\n", Fibonacci(n));
    return 0;
}


这个方法是正确的吗?


没有细细研究,不过fib[n]=Fibonacci(a)*Fibonacci(b-1) + Fibonacci(a+1)*Fibonacci(b);好像是矩阵乘法。

如果把数组去掉,第归改循环,好像就是F数列的矩阵算法,原理差不多。

 

作者:justforfun626

专家分:18460

级别:93级别:93级别:93级别:93级别:93级别:93级别:93级别:93

发表时间:2008-2-16 13:19:00    [回复]  [引用]
35楼
引用

有没有人注意到我在10楼所回复的?再贴一遍
分成两个接近的数(差1),近似于二分计算

#include <stdio.h>

unsigned long long fib[200]={0, 1, 1};

unsigned long long Fibonacci(unsigned n)
{
    unsigned a, b;
    if (fib[n]) return fib[n];
    b = (a=n>>1) + (n&1);
    return fib[n]=Fibonacci(a)*Fibonacci(b-1) + Fibonacci(a+1)*Fibonacci(b);
}

int main(void)
{
    unsigned n;
    scanf("%u", &n);
    printf("%llu\n", Fibonacci(n));
    return 0;
}



To MasterRaySoul:

Your algorithm is correct and excellent, its correctness can be easily proved by induction.

However, your implementation is using array, which uses too much memory.

It will explode just like mine in ruby, criticized by rickone.

I think you should use STL Hash Table to use memory on demand.

I have implemented your algorithm in Ruby, it is fast and easily reached fib(1000000).

Thank you for providing the excellent algorithm. I will credit you on my website for my ruby implementation. 

The link will be provided when it is ready.

Thanks a lot!

  最后修改于2008-2-16 13:22:00

作者:justforfun626

专家分:18460

级别:93级别:93级别:93级别:93级别:93级别:93级别:93级别:93

发表时间:2008-2-16 14:16:00    [回复]  [引用]
36楼
Now, it is uploaded

引用

Q. How to calculate big number (such as 1000000) fibonacci number in O(log(n)) time without using out all the memory, and not causing stack overflow?

A: This algorithm is provided by MasterRaySoul

Its correctness can be easily proved by induction. The time complexity is O(log(n)). 

The original code was in C, and had space complexity of O(n), because the huge nature of fibonacci number, it will run out of memory very fast. 

Now, I combined the algorithm with Andrew Johnson's memory on demand Hash implemetation, space complexity is also reduced to O(log(n)), made fib[1000000] without stack overflow and no memory problem either. 

Here is the code. Enjoy!


fib_d = Hash.new{ |h, n| 
  if (n<2) 
    h[n] = n
  elsif n == 2
    h[n]=1
  else
    a = n/2
    b = a + n%2
    h[n] = h[a]*h[b-1] + h[a+1]*h[b]
  end
}
puts fib_d[1000000]



Copied from 
http://bobcat.webappcabaret.net/javachina/faq/ruby_01.htm#ruby_Q016

Thanks MasterRaySoul!!!!

  最后修改于2008-2-16 14:17:00

作者:bpttc

专家分:8790

级别:44级别:44级别:44级别:44级别:44级别:44级别:44

发表时间:2008-2-16 14:18:00    [回复]  [引用]
37
这贴很邪恶...

  最后修改于2008-2-16 14:18:00

[首页] [上页]  [下页] [尾页]     共有 37 回帖 当前第 2 页(共2页 20帖/页)     跳转至第
回 帖 快速回帖 发 新 帖 刷新版面

版主管理:  删除此帖   转贴   置顶   加入精华   强制结帖   >>>进入管理页面