我在Real World Haskell上发表了以下句子:
懒惰的评价有一些怪异的效果。假设我们想要找到 k个未排序列表的k个最小值元素。在传统的 语言,显而易见的方法是对列表进行排序并采取 前k个元素,但这很贵。为了提高效率,我们愿意 而是写一个特殊的函数,在一次传递中获取这些值, 它必须执行一些中等复杂的簿记。在 Haskell,排序然后采取的方法实际上表现良好:懒惰 确保列表仅排序足以找到k minimal 元件。
他们为此提供了代码实现:
minima k xs = take k (sort xs)
但是这样吗?我想即使在Haskell中它也应该完整地列出k
元素。 (想象一下,列表末尾的数字最小)。我在这里错过了什么吗?
答案 0 :(得分:1)
(只需将我的评论放在这里回答)遍历整个列表并不等同于对其进行排序。假设执行快速排序,您可以在其中围绕数据透视表对列表进行分区,然后递归地对列表的左半部分和右半部分进行排序。如果您只是要求左半部分的元素,则无需对右半部分进行排序。可以递归地应用此参数。因此,如果您在排序后从k
长度列表中提取n
个元素,则复杂度为O(n + klog k)
而非O(n log n)
。正如@MoFu指出的,Heinrich有一篇很好的博文here。