Java 8 Lambda 表达式,用于求解斐波那契(非递归方式)

我是在Java 8中使用Lambda表达式功能的初学者。Lambda 表达式在解决质数检查、阶乘等程序时非常有用。

但是,它们可以有效地用于解决像斐波那契这样的问题,其中当前值取决于前两个值的总和。我已经很好地解决了使用Lambda表达式有效解决质数检查问题。下面给出了相同的代码。

boolean checkPrime=n>1 && LongStream.range(2, (long) Math.sqrt(n)).parallel().noneMatch(e->(n)%e==0);

在方法的上述代码中,我们使用范围中的当前值()进行评估。但是对于斐波那契问题,我们需要前两个值。noneMatche

我们如何才能实现它?


答案 1

最简单的解决方案是使用 s 流:Pair

Stream.iterate(new long[] { 1, 1 }, p -> new long[] { p[1], p[0] + p[1] })
      .limit(92)
      .forEach(p -> System.out.println(p[0]));

由于缺乏标准对类型,它使用双元素数组。此外,我使用,因为我们无法使用值来评估更多元素。但它很容易适应:.limit(92)longBigInteger

Stream.iterate(new BigInteger[] { BigInteger.ONE, BigInteger.ONE },
               p -> new BigInteger[] { p[1], p[0].add(p[1]) })
      .forEach(p -> System.out.println(p[0]));

这将一直运行,直到您没有足够的内存来表示下一个值。

顺便说一句,要从流中获取第n个元素:

Stream.iterate(new long[] { 1, 1 }, p -> new long[] { p[1], p[0] + p[1] })
      .limit(91)
      .skip(90)
      .findFirst()
      .get()[1];

答案 2

要获得第N个斐波那契元素(使用约简):

Stream.iterate(new long[] {1, 1}, f -> new long[] { f[1], f[0] + f[1] })
    .limit(n)
    .reduce((a, b) -> b)
    .get()[0];

这是正在发生的事情:

  • Stream::迭代 - 生成成对的数字,每个数字包含两个连续的斐波那契元素。我们必须使用对,因为我们只能通过“迭代”访问最后一个元素,而不是两个或更多个以前的元素,所以要生成一个新对,我们得到最后一个对,它已经包含两个前一个斐波那契元素,并产生下一个对。要获得第 N 个斐波那契元素,我们只需要从第 N个对中获取左值。

  • .limit(n) - 保留前 N 对,并排除其余对。

  • .reduce((a, b) -> b) - 从上一步的 N 对流中获取最后一对。

  • .get()[0] - 从对中提取斐波那契元素(对的左值)