这个时间和空间的复杂性是什么:
def isPalindrome[A](x: Seq[A]): Boolean = x match {
case h +: middle :+ t => h == t && isPalindrome(middle)
case _ => true
}
是否取决于Seq
的实施?由于IndexedSeq
O(1)
应该O(n)
尾{vs LinearSeq
O(n)
由于递归调用堆栈,空间复杂度是import scala.annotation.tailrec
@tailrec def isPalindrome[A](x: Seq[A]): Boolean = x match {
case h +: middle :+ t => h == t && isPalindrome(middle)
case _ => true
}
还是Scala会自动进行尾调用优化?
{{1}}
答案 0 :(得分:1)
是否依赖于Seq的实施?因为对于LinearSeqs,IndexedSeq应该有O(1)尾对比O(n)
我通常会假设,但提取器实际上是O(n)
。任何Seq
的提取器都是scala.collection.:+
,其中列表的O(n)
为最后一个,O(n)
为最后一个。这两个代码如下:
def init: Repr = {
if (isEmpty) throw new UnsupportedOperationException("empty.init")
var lst = head
var follow = false
val b = newBuilder
b.sizeHint(this, -1)
for (x <- this) { // O(n)
if (follow) b += lst
else follow = true
lst = x
}
b.result
}
def last: A = {
var lst = head
for (x <- this) // O(n)
lst = x
lst
}
由于递归调用堆栈,空间复杂度是否为O(n),或者Scala是否自动进行尾调用优化?
我看到代码确实有这个优化。这是有道理的,因为t && isPalindrome(middle)
允许Scala关闭当前调用堆栈,将t
传递给下一个堆栈&&
,因此它可以进行尾递归优化。
使用Vector
我们可以实现O(1)
时间:
object ends {
def unapply[T](t: Vector[T]): Option[(T, Vector[T], T)] =
if (t.length < 2) None
else Some((t.head, t.drop(1).dropRight(1), t.last))
}
def isPalindrome[A](x: Vector[A]): Boolean = x match {
case ends(i, middle, l) => i == l && isPalindrome(middle)
case _ => true
}