在Scala中,列表有reverse
方法。这种方法的复杂性是什么?简单地使用原始列表并始终记住列表与我们期望的相反,或者在操作之前明确使用reverse
是不是更好。
编辑:我真正感兴趣的是获取原始列表的最后两个元素(或反向列表的前两个)。
所以我会这样做:
val myList = origList.reverse
val a = myList(0)
val b = myList(1)
这不是一个循环,只是我的库中的一次性事物......但如果其他人使用该库并将其置于循环中,则不在我的控制范围内。
答案 0 :(得分:14)
查看来源,您可能会合理地预期O(n)
:
override def reverse: List[A] = {
var result: List[A] = Nil
var these = this
while (!these.isEmpty) {
result = these.head :: result
these = these.tail
}
result
}
如果在您的代码中,您能够以相反的顺序迭代遍历列表,并且以正向顺序进行迭代,那么执行此操作更高效而不是反转List
事实上,如果涉及使用原始列表的替代操作在 less 而不是O(n)
时间内工作,那么就有了一个真正的论据。如果你更依赖它(特别是如果在其他循环中使用,如oxbow_lakes在下面指出的那样),使算法渐近更快会产生巨大的差异。
总的来说,虽然我希望你反转一个列表的任何东西都意味着你关心一个非平凡数量的元素的相对排序,所以无论你做什么本质上都是O(n)无论如何。 (对于其他数据结构,例如二叉树,这可能不是这样;但是列表是线性的,在极端情况下,即使reverse . head
也不能在单独链接列表的O(1)时间内完成。 )
因此,如果您在两个O(n)选项之间进行选择 - 对于浩大的大多数应用程序,在迭代时间内缩短几纳秒并不会真正获得任何东西。因此,使代码尽可能可读是“最好的” - 这意味着调用reverse
然后迭代,如果这与您的意图最接近。
(如果您的应用太慢,和分析显示此列表操作是一个热点,然后您可以考虑如何为了提高效率。考虑到你当时的额外背景,在这一点上可能会对你当前的候选人提出不同的选择。)