有效计算列表中k个最大数字之和的方法?

时间:2015-03-11 00:30:26

标签: arrays algorithm list data-structures

我正在阅读一些练习面试问题,我对这个问题有疑问。假设一个随机整数列表,每个整数在1和1之间。 100,计算k个最大整数的总和?讨论空间和时间的复杂性以及如果每个整数在1和1之间,方法是否会改变。 m在哪里变化?

我的第一个想法是对数组进行排序并计算最大k数的总和。然后,我想如果我使用二叉树结构,我可以从右下角的树开始。我不确定我的方法是否会改变数字是1到100还是1到m?有关最有效方法的想法吗?

3 个答案:

答案 0 :(得分:4)

最有效的方法可能是使用randomized quickselect之类的东西。它不会完成排序步骤,而只是从quicksort执行分区步骤。如果你不希望某个特定顺序的k个最大整数,那么这就是我的方式。它需要线性时间,但分析并不是很简单。我对此几乎没什么影响。此外,您可以编写代码,以便在对数组进行分区时计算总和。

Time: O(n)
Space: O(1)

替代使用具有线性时间保证的counting sort等内容进行排序。如你所说,这些值是固定范围内的整数,它会很好地工作。随着m增加,空间需求增加,但计算总和在桶内非常有效。

Time: O(m) in the worst case (see comments for the argument)
Space: O(m)

答案 1 :(得分:3)

我会说排序可能是不必要的。如果k很小,那么您需要做的就是维护一个排序列表,该列表截断k最大元素之外的元素。

在最差的情况下,添加的元素最大化时,每个步骤都应该是O(k)。但是,平均情况情况要好得多,在一定数量的元素之后,大多数元素应该小于列表中的最后一个元素,操作将是O(log(k))

答案 2 :(得分:1)

一种方法是使用最大大小为k的min-heapimplemented as a binary tree)。要查看新元素是否属于堆,只有O(1),因为它是一个最小堆,并且最小元素的检索是一个恒定时间操作。沿着O(n)列表的每个插入步骤(或者在元素太小而不能插入的情况下的非插入...)是O(log k)。最后的树遍历和求和步骤是O(k)。

总复杂性:

O (n log k + k) = O(n log k)

除非您的计算机上运行多个内核,否则并行计算是一种选择,只能在结束时进行求和。动态计算增加了额外的计算步骤,而根本没有真正降低时间复杂度(实际上你需要做更多的计算)。无论如何,你总是要总和k个元素,那么为什么不避免额外的加法和减法步骤?