`
rijin
  • 浏览: 140008 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

这样实现Fibonacci最快最简单!

    博客分类:
  • Java
阅读更多
大家都知道Fibonacci数列(一般译为斐波那契数列),比如:0, 1, 1, 2, 3, 5, 8, 13, 21...这是一个通过重复计算生成数列的好例子:f(n) = f(n-2) + f(n-1)。我们可以写一个计算第n个(从0开始)Fibonacci数的简单代码:
public class Fibonacci {

    public int fib(int n) {
        if (n == 0 || n == 1) return n;

        System.out.println("calculating fib(" + n + ")");
        return fib(n - 2) + fib(n - 1);
    }

}
 
让我们打印下计算第7个Fibonacci数的:
public class Main {

    public static void main(String[] args) {
        System.out.println("fib(7) = " + new Fibonacci().fib(7));
    }

}
 
结果如下:
calculating fib(7)
calculating fib(5)
calculating fib(3)
calculating fib(2)
calculating fib(4)
calculating fib(2)
calculating fib(3)
calculating fib(2)
calculating fib(6)
calculating fib(4)
calculating fib(2)
calculating fib(3)
calculating fib(2)
calculating fib(5)
calculating fib(3)
calculating fib(2)
calculating fib(4)
calculating fib(2)
calculating fib(3)
calculating fib(2)
fib(7) = 13
 
发现没,这样计算的步骤太多太复杂了!上面代码里有着严重的性能问题:fib(n)的调用次数随着n的增长呈指数级增长。
我们可以用一个加缓存的方法来优化,当然这个缓存是要线程安全的:
public class Fibonacci {

    private Map cache = new ConcurrentHashMap<>();

    public int fib(int n) {
        if (n == 0 || n == 1) return n;

        Integer result = cache.get(n);

        if (result == null) {
            synchronized (cache) {
                result = cache.get(n);

                if (result == null) {
                    System.out.println("calculating fib(" + n + ")");
                    result = fib(n - 2) + fib(n - 1);
                    cache.put(n, result);
                }
            }
        }

        return result;
    }

}
 
计算过程和结果如下:
calculating fib(7)
calculating fib(5)
calculating fib(3)
calculating fib(2)
calculating fib(4)
calculating fib(6)
fib(7) = 13
 
上面代码会先检查下缓存里的结果。如果这步调用还没有结果的,就计算出来并且把结果放进缓存。为了更好的性能,用了一个双重检查锁定(译者注:其实这里可以展开讨论下,为什么要加锁,如果不加锁会怎么样),可惜的是代码变复杂了。
 

Java8来拯救小伙伴们了!

 

让我们看下ConcurrentHashMap在Java8里一个新方法:
public V computeIfAbsent(K key, Function mappingFunction)
 
这个ConcurrentHashMap.computeIfAbsent有什么用呢?如果在map里没找到给定的key值所对应的entry,它会调用mappingFunction(key)来计算出哈希值,然后执行put(key,value)操作,整个过程都是保证原子性的。实际上它就是替我们完成了一堆在Java8版本前我们要自己写的脏活累活。这样现在的代码就非常简单了(当然还要感谢Java8里的新特性lambda):
public class Fibonacci {

    private Map cache = new ConcurrentHashMap<>();

    public int fib(int n) {
        if (n == 0 || n == 1) return n;

        return cache.computeIfAbsent(n, (key) -> {
            System.out.println("calculating fib(" + n + ")");
            return fib(n - 2) + fib(n - 1);
        });
    }

}
 
当然,打印语句那里,还可以通过lambda继续简化:
public class Fibonacci {

    private Map cache = new ConcurrentHashMap<>();

    public int fib(int n) {
        if (n == 0 || n == 1) return n;

        return cache.computeIfAbsent(n, (key) -> fib(n - 2) + fib(n - 1));
    }

}
 
本文只是写了Java8里通过ConcurrentHashMap的一个新方法,简化了代码的小例子,其实Java8里让人点赞的新特性还有很多...
(英文原文出自这里)
本文同时发表在本人博客www.newhottopic.com  ,并非转载。
6
7
分享到:
评论
1 楼 Grumpy 2014-03-13  
递归的精髓在于其想法,你把Fibonacci写的也太复杂了吧
    public static int getFibocacci(int index) {
        int b = 0, n = 1;
        for (int i = 2; i <= index; i++) {
            if (i % 2 == 0) {
                b += n;
            } else {
                n += b;
            }
        }
        return index < 2 ? index : (b > n ? b : n);
    }

相关推荐

    用Python轻松实现斐波那契数列-递归函数详解!

    在Python中,我们可以使用递归函数来轻松地实现斐波那契数列。递归是一种解决问题的方法,它将问题分解为更小的子问题,直到子问题变得足够简单可以直接求解。在这个场景下,我们定义一个函数,该函数调用自身来计算...

    斐波那契堆(fibonacci)

    2. 删除最小元素:斐波那契堆通过“瀑布修剪”(Fibonacci Heap Deletion)策略来优化这个操作。当删除最小元素时,会将所有与其相邻的子节点提升到其位置,这个过程可能引发树的重构,但总体上保证了操作的时间...

    如何使用Python实现斐波那契数列

    斐波那契数列是一个经典的数学概念,最早由印度数学家Gopala提出,而意大利数学家Leonardo Fibonacci则是对其进行了深入研究。斐波那契数列定义简单,每个数是前两个数的和,起始值为0和1。数列的前几个数为0, 1, 1,...

    C#实现斐波那契数列的几种方法整理

    递归算法是最简单的实现斐波那契数列的方法之一,其思想是将问题分解成更小的子问题,然后通过递归函数来解决这些子问题。例如: ```csharp public static long CalcA(int n) { if (n ) return 0; if (n ) return ...

    C语言编写斐波那契序列(数据结构)

    递归是最直观的实现方式,通过函数自身调用来计算F(n)。递归代码简洁易懂,但效率较低,因为它会进行大量的重复计算。以下是一个基本的递归实现: ```c int fibonacci(int n) { if (n ) return n; return ...

    求解fibonacci数列的前20项

    - **性能提升**:考虑到Fibonacci数列的增长速度非常快,对于非常大的数值,可以采用更高效的算法(如矩阵快速幂)来减少计算时间。 ### 总结 通过上述分析可以看出,给定的C语言代码实现了求解Fibonacci数列前20项...

    迭代法求最小值.zip_斐波那契查找_最小值matlab_费波拉契数列法求解最小值_迭代搜索_迭代法

    斐波那契查找法在MATLAB中的实现往往比简单的线性搜索更快,因为它利用了黄金分割比例的性质,减少了无效的搜索步骤。然而,与二分查找相比,斐波那契查找法在最坏情况下的时间复杂度相同,都是O(log n),但在某些...

    用Java实现超大Fibonacci数的计算 (1).pdf

    【Java实现超大Fibonacci数的计算】 Fibonacci数列是数学中一个非常重要的概念,由13世纪意大利数学家Fibonacci提出。它起源于一个关于兔子繁殖的问题,随着时间的推移,Fibonacci数列在多个领域得到了广泛应用,...

    斐波那契数列前20项.docx

    迭代法的一个简单实现是使用两个变量 `a` 和 `b` 分别存储当前项和前一项的值,初始化为1。然后通过一个循环,每次更新 `a` 和 `b` 的值,直到计算出第20项。这样可以避免递归带来的额外开销。 ```c #include int...

    Fibonacci数列三种求和方式

    递归是最直观的方法,直接基于斐波那契数列的定义来实现。函数定义如下: ```python def fibonacci_recursive(n): if n return 0 elif n == 1: return 1 else: return fibonacci_recursive(n - 1) + ...

    Python中斐波那契数列的四种写法.pdf

    斐波那契数列是一个在计算机科学和数学中常见的数列,它的定义是这样的:F(0) = 1, F(1) = 1, 且对于所有 n &gt; 1,F(n) = F(n-1) + F(n-2)。这个数列的前几项是1, 1, 2, 3, 5, 8, 13, ...。斐波那契数列在很多领域都...

    Fibonacci:打印斐波那契数字

    斐波那契序列是计算机科学和数学中一个著名的数列,它的定义非常简单:第一项是0,第二项是1,之后每一项都是前两项的和。用数学公式表示就是 F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) (n &gt;= 2)。这个序列在自然...

    斐波那契数列python

    以下是一个简单的Python迭代实现: ```python def fibonacci(n): fib_sequence = [0, 1] while len(fib_sequence) fib_sequence.append(fib_sequence[-1] + fib_sequence[-2]) return fib_sequence[n] ``` ...

    datastructure_斐波那契堆_二项堆_

    Fibonacci_Heap.cpp 文件很可能包含了实现斐波那契堆的主要函数和数据结构,如节点结构定义、插入、删除、合并和降低键值等操作。而binary_heap.h 文件则可能包含二项堆的相关定义和操作实现。 在实际应用中,选择...

    fibonacci:比较Java中的三种不同的Fibonacci实现

    这是一个简单的程序,可用于比较Java中Fibonacci算法的3种不同实现,以了解计算时间。 这三个实现如下: 递归斐波那契 尾递归斐波那契 迭代斐波那契 结果表明,迭代一次是最快的,而递归一次是最慢的。 因此,递归...

    二项式堆、斐波纳契(Fibonacci)堆和Pairing堆

    二项式堆、斐波纳契堆和Pairing堆是数据结构中的三种高效优先队列实现,它们在处理大量数据的排序、最优化问题以及图形算法等领域有着广泛的应用。这三类堆都属于堆数据结构,但各自具有不同的特性和操作效率。 1. ...

    斐波那契数列 - 非常简单:这将打印一组斐波那契数列-matlab开发

    在“fibonacci.zip”这个压缩包中,可能包含了上述各种实现斐波那契数列的MATLAB代码示例,供学习者参考和实践。通过学习这些代码,你可以加深对递归和迭代的理解,以及如何在MATLAB中有效地处理序列和数组。同时,...

    Fibonacci Seri:这是显示如何生成斐波那契数字的代码-matlab开发

    其中最简单的方法是通过循环结构实现。下面是一种使用for循环的实现方式: ```matlab function fibo = fibonacci(n) fibo = zeros(1, n); fibo(1) = 0; fibo(2) = 1; for i = 3:n fibo(i) = fibo(i-1) + fibo...

    (2021-2022年收藏)优化方法中0.618法和fibonacci法源程序原创matlab.doc

    总之,0.618法和斐波那契法是数值优化领域中两种简单而实用的搜索策略,它们提供了一种基于比例或数列的迭代方式来逼近函数的局部最小值,适用于教育和科研中的数值计算实践。在MATLAB环境中,可以通过编写相应的...

Global site tag (gtag.js) - Google Analytics