您的位置:首页 > 编程语言 > Java开发

使用Java8优化Fibonacci数

2014-03-22 19:34 323 查看
Fibonacci数的定义如下:



在Java中,该算法的非常好容易实现

public static long fibonacci(int x) {
   if(x==0 || x==1)
      return x;
   return fibonacci(x-1) + fibonacci(x-2);
}
但是该算法存在严重的效率问题:对于每一个数字,该算法会递归调用自身两次,其中每次一个分支都会重新计算另一个分支的一部分,例如下面计算fibonacci(5)的计算细节的树形图如下:



从上图可知,该算法存在严重的重复计算。

但是在Java8中,利用其两个新特性,可以优化该算法。

思路如下:

上面算法最严重的问题就是存在太多的重复计算,因此我们可以使用内存来尽量规避这个问题,也就是说,提供一种缓存结果的机制来规避重复计算。

在Java中,可以将Fibonacci数缓存在哈希表或者Map中,这样只需要最左边分支使用递归来计算,并将计算结果缓存到Map中,所有的右边分支只需到哈希表中查询,

在哈希表中找到中的正确结果返回即可,不需要再次计算。

在Java8给Map增加了一些新方法,简化了上面这个思路的实现,比如computeIfAbsent(key, function),该函数key可以为需要计算的数字,而function为一个能够递归计算Fibonacci数的lambda表达式,如果key对应的Fibonacci数不在map中,则该lambda表达式能够正确的计算出Fibonacci数

首先要定义一个Map,同时缓存fibonnaci(0) 和 fibonacci(1)的结果

private static Map<Integer,Long> memo = new HashMap<>();
static {
   memo.put(0,0L); //fibonacci(0)
   memo.put(1,1L); //fibonacci(1)
}
剩下的递归部分可以如下定义:

public static long fibonacci(int x) {
   return memo.computeIfAbsent(x, n -> fibonacci(n-1) + fibonacci(n-2));
}
从上面可以看到,如果x的fibonnaci数不在map中,computeIfAbsent方法可以用提供的lambda表达式来计算fibonnaci数的左边部分,然后右边部分直接使用map中缓存的结果,这样就规避了大部分的重复计算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: