Algorithm 如何在数组中找到多个最小元素?

Algorithm 如何在数组中找到多个最小元素?,algorithm,big-o,recurrence,quickselect,Algorithm,Big O,Recurrence,Quickselect,我正在努力完成我的作业,需要一点推动-问题是设计一个算法,在O(nlogm)时间内找到多个最小元素1如果我理解正确,你有一个包含m个索引的向量K,您希望为k中的每个k找到A的第k个排序元素。如果k包含最小的m个索引(即k=1,2,…,m),那么这可以在线性时间T=O(n)内轻松完成,方法是使用quickselect查找元素k_m(因为所有较小的元素都将位于quickselect末尾的左侧)。所以我假设K可以包含任意一组m指数 实现这一点的一种方法是同时在所有K上运行quickselect。这是算

我正在努力完成我的作业,需要一点推动-问题是设计一个算法,在O(nlogm)时间内找到多个最小元素
1如果我理解正确,你有一个包含m个索引的向量K,您希望为k中的每个k找到A的第k个排序元素。如果k包含最小的m个索引(即k=1,2,…,m),那么这可以在线性时间T=O(n)内轻松完成,方法是使用quickselect查找元素k_m(因为所有较小的元素都将位于quickselect末尾的左侧)。所以我假设K可以包含任意一组m指数

实现这一点的一种方法是同时在所有K上运行quickselect。这是算法

QuickselectMulti(A,K)
If K is empty, then return an empty result set
Pick a pivot p from A at random
Partition A into sets A0<p and A1>p.
i = A0.size + 1
if K contains i, then remove i from K and add (i=>p) to the result set.
Partition K into sets K0<i and K1>i
add QuickselectMulti(A0,K0) to the result set
subtract i from each k in K1  
call QuickselectMulti(A1,K1), add i to each index of the output, and add this to the result set
return the result set
由于m每次下降一半,因此
n
将在该总和中显示
log m
次。要实际导出预期的运行时间需要更多的工作,因为您不能假设pivot将两个数组一分为二,但是如果您完成计算,您将看到运行时间实际上平均为O(n log m)


编辑:通过运行p=Quickselect(A,k_i),其中k_i是k的中间元素,而不是随机选择p,对该算法的分析可以简化此操作。这将保证每次将K分成两半,因此递归调用的数量将正好是log m,而且由于quickselect在线性时间内运行,结果仍然是O(n log m)。

我发现您的问题陈述可能会重复。什么是
m
?为什么在
o(n)
中使用little oh?谢谢,100个最大数字的问题看起来很相似。但我不明白他们是怎么想到提姆的@NPE M基本上是我们需要的ki数,如果我们需要第一、第二和第三个最小的数,M=3。这个问题的公认答案是O(n log M)。谢谢,伙计,这正是我需要的!对不起,解释得不好。但只有一个问题——为什么每次m都被切成两半?每次,m被分成两部分m1和m2,这样m1+m2=m(或者如果指数i属于K,m1+m2=m-1)。它们对应于K的两个子集K1和K2,由索引i划分。就像我说的,你不能假设每次K都会被精确地减半,所以你还有一些工作要做,但是如果你运行计算,你会发现预期的运行时间仍然是O(n log m)。想想看,你可以通过运行p=Quickselect(A,K_I)来选择p来简化这个过程其中k_i是k的中间元素。这将保证每次k被分成两半,因此递归调用的数量将正好是log m。还有一个问题-add(i=>p)意味着在结果上加一个[i],对吗?基本上是的。我将结果表示为从索引到值的映射,因此这意味着将“I映射到p”对添加到结果映射。注意这里a[i]=p。因此,是的,您可以很容易地忘记索引,只返回值集,在这种情况下,您可以说“将p添加到结果集”。
T = n + 2T(n/2,m/2)
  = n + n + 4T(n/4,m/4)
  = n + n + n + 8T(n/8,m/8)