" oneToEach"函数为List[Int]
的每个元素添加1。第一个函数不是尾递归,而后者是。
如果我有一个百万长度的List [Int]我传入这两个函数,哪个会表现得更好?更好=更快或更少的资源使用。
// Add one to each element of a list
def oneToEach(l: List[Int]) : List[Int] =
l match {
case Nil => l
case x :: xs => (x + 1) :: oneToEach(xs)
}
...
def oneToEachTR(l: List[Int]) : List[Int] = {
def go(l: List[Int], acc: List[Int]) : List[Int] =
l match {
case Nil => acc
case x :: xs => go(xs, acc :+ (x + 1))
}
go(l, List[Int]())
}
如果我理解,第一个函数的算法复杂度为O(n),因为它需要递归列表中的每个项目并添加1.
对于oneToEachTR
,它使用:+
运算符,我的read是O(n)复杂度。由于在列表中每个递归/项使用此运算符,最坏情况算法复杂度是否变为O(2 * n)?
最后,对于百万元素列表,后者函数在资源方面的表现会更好吗,因为它的尾递归?
答案 0 :(得分:4)
关于
对于
oneToEachTR
,它使用:+
运算符,我读过这个运算符的复杂度为O(n)
。由于在列表中每个递归/项使用此运算符,最坏情况的算法复杂度是否变为O(2*n)
?
不,它变为O(n^2)
对于足够大的O(n^2)
,尾递归不会保存O(n)
算法与n
; 100万肯定就足够了!
n
元素列表。:+
将遍历0个元素(acc
最初为空)并附加1: 1个操作。1 + 2 + 3 + ... + n
= n(n+1)/2
= (1/2)n^2 + n/2
。这是“按”n^2
或O(n^2)
。