在我阅读this (page 14)时,我遇到了这个算法:
function fib2(n)
if n = 0 return 0
create an array f[0 : : : n]
f[0] = 0, f[1] = 1
for i = 2 : : : n:
f[i] = f[i 1] + f[i 2]
return f[n]
如果我想使用模式匹配在Scala中实现它,有没有办法在模式匹配部分创建一个List,以便在最终的return语句中使用它?
这些都是很好的答案,但我想我仍然想知道是否可以定义一个仅在模式匹配中使用的变量。我知道你可以在Haskell中做到这一点,但我想知道它是否在Scala中可行。
答案 0 :(得分:13)
lazy val fib: Stream[Int] = Stream.cons(0,Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))
fib.take(n).last 将返回结果
另一种流解决方案。它定义了无限的斐波纳契数列。是的,它是救援和无限定义,但所有计算都是在调用take时执行的
只需在这里查看更多有趣的代码。
link
答案 1 :(得分:10)
我认为这里不需要模式匹配。对Scala的直接转换看起来基本相同:创建一个数组f
并循环遍历索引2 until n
。
def fib(n: Int): Array[Int] = {
val f = new Array[Int](math.max(2, n))
f(0) = 0
f(1) = 1
for (i <- 2 until n)
f(i) = f(i-1) + f(i-2)
f
}
如果你想变得更加漂亮,lazy stream怎么样?
def fibFrom(a: Int, b: Int): Stream[Int] = a #:: fibFrom(b, a + b)
fibFrom(0, 1).take(8).toList // returns List(0, 1, 1, 2, 3, 5, 8, 13)
答案 2 :(得分:2)
以下是jeela解决方案的重构。我认为最好始终与头部一起工作,因为它要快得多。最终的reverse
并没有太大的伤害。
def fib(s:Int) = {
def f(s:Int):List[Int] = s match {
case x if x < 0 => Nil
case 0 => List(0)
case 1 => List(1,0)
case _ => val fibs = f(s-1); (fibs.head + fibs.tail.head) :: fibs
}
f(s).reverse
}
答案 3 :(得分:1)
我认为使用懒惰流是更好的方法,但只是为了展示我的肌肉:
def fib(s:Int):List[Int] = s match {
case 0 => Nil
case 1 => 0::fib(s-1)
case 2 => 0::1::fib(s-2)
case _ => fib(s-1):::fib(s-1).takeRight(2).sum::Nil
}