这是我在网上发现的一个有趣的问题。给定一个包含n
个数字的数组(没有关于它们的信息),我们应该以线性时间预处理数组,以便我们可以返回 k
中的O(k)
个最小元素时间,当我们得到一个数字1 <= k <= n
我和一些朋友一直在讨论这个问题,但没有人能找到解决方案;任何帮助将不胜感激!
答案 0 :(得分:14)
对于预处理步骤,我们将在同一数据集上多次使用基于分区的选择。
使用算法找到 n / 2 -th数字。现在数据集被分为两半,一半,一半。在下半部再次找到中点。在它的下部分区做同样的事情等等......总的来说这是O(n)+ O(n / 2)+ O(n / 4)+ ... = O(n)。
现在,当您必须返回 k 最小元素时,请搜索最近的 x &lt; k ,其中 x 是分区边界。可以返回它下面的所有内容,并且从下一个分区返回 k - x 数字。由于下一个分区的大小为 O(k),因此为 k - x 编号运行另一个选择算法将返回其余分区。
答案 1 :(得分:1)
我们可以在线性时间内找到列表和分区的中位数。
然后我们可以使用以下算法:维护大小为2k
的缓冲区。
每次缓冲区变满时,我们会找到它周围的中位数和分区,只保留最低的k
元素。
这需要n/k
查找中位数和分区步骤,每个步骤在传统的快速选择中花费O(k)
时间。这种方法只需要O(n)
次。
另外如果您需要排序的输出。
这会增加额外的O(k log k)
时间。总的来说,此方法仅需要O(n + k log k)
时间和O(k)
空间。