我有一个未排序的数字列表,我想要一个算法,这样我就可以得到第一个R元素的排序列表,但由于这个R对于不同的测试用例可能是不同的,我不想每次为第一个R排序数组元素。有没有办法让我完成这件事。一种可能的方法是保持向量数组,使得我有前1个数字排序,然后前2个数字排序,然后前3个数字排序等等,但它将需要1log1 + 2log2 + 3log3 + .... + nlogn时间,这是N ^ 2logN的复杂性。更快的方法可能吗?
答案 0 :(得分:2)
在这种情况下,好的旧插入排序似乎比O(N
^ 2 lg N
)更好,因为您不需要为每个{{从头开始排序元素1}}。
假设您在R
中拥有n
数组的已排序的第一个n
元素的副本。
只需将1..R-1
- th元素插入R
第一个元素(即O(R))的排序数组的副本中,即可获得R-1
个第一个元素的排序数组。
如果你想要R
中N
的每个R
的结果,那就是O(1..N
^ 2),但实际上这个结果会小于O(N ^ 2),因为你可以按需生成排序数组,从最后排序的数组开始,元素少于R
。
答案 1 :(得分:2)
我们可以使用O(n log n)
空格来保留合并排序的部分结果。然后,返回排序的第一个R
元素的上限类似于合并log n
排序列表。我找到了one reference,用于合并k
n
的{{1}}排序列表O(n * log k)
,这将使我们O(n * log log n)
,但希望很多查询都是均匀的效率更高。
13,15,12,4,18,1,23,17,6,2 ->
| 1 2 4 6 12 13 15 17 18 23 |
| 4 12 13 15 18 | 1 2 6 17 23 |
| 13 15 | 4 12 18 | 1 23 | 2 6 17 |
| 13 | 15 | 12 | 4 | 18 | 1 | 23 | 17 | 6 | 2 |
答案 2 :(得分:1)
你可以试试quicksort,但不能完全做到。我听说Haskell以类似的方式做到了。
这几乎是通常的快速排序,但是你推迟了可以推迟的工作。
对于第一个元素,只需快速选择跳过与第一个元素无关的范围。但是对于每个下一个元素,您应该查找尚未分区的范围,但是需要它并对它们进行分区。
第一个元素的时间将为O(n)
(并且您不太可能获得更好的效果),整个时间将为O(n * log n)
。
用于存储范围位置的额外内存似乎是O(log n)
,但我没有想到这一点足以确定。
更正:如果您需要每次输出整个子数组,只有在您一次输出数字时才会输出O(n^2)
,这将是O(n * log n)
。