如何对O(n)中给定范围的列表进行排序

时间:2013-12-01 04:46:32

标签: algorithm sorting

如果我有一个大小为n的列表,并且我知道列表中的数字将在1到2n之间,那么在最坏的情况是O(n)的情况下,我将如何解决它?

我在想,如果它介于1和n之间,我可以取数字并将其与该数字的数值交换 - 1然后如果有任何重复则不会排序。

我在考虑类似的方法,列表中的数字介于1和2n之间,但我似乎无法弄明白。有什么帮助吗?

4 个答案:

答案 0 :(得分:6)

在您的情况下,

Counting Sort 可以在 O(n)中运行。看看维基百科的定义

  

计数排序是一种用于对对象集合进行排序的算法   根据小整数的键;也就是说,它是一个整数   排序算法。它通过计算对象的数量来操作   拥有每个不同的键值,并使用这些计数的算术   确定输出序列中每个键值的位置。它的   运行时间与项目数量和差异呈线性关系   最大和最小键值之间,所以它只适合   直接用于键的变化不是的情况   显着大于项目数

http://en.wikipedia.org/wiki/Counting_sort

答案 1 :(得分:4)

您通常需要非比较排序才能在O(n)时间内排序,但这是因为您已经获得了某些信息。有三种“主要”非比较排序算法可供选择:计数排序,基数排序和桶排序。

如果您知道输入是小整数,请使用计数排序。根据维基百科的说法,“计数排序仅适用于密钥变化不大于项目数量的情况。” http://en.wikipedia.org/wiki/Counting_sort

如果要排序的所有数字具有相同的整数,则可以使用基数排序。例如:211,311,122。

铲斗排序似乎是您的最佳选择。您的方法听起来不错,但您不需要1到2n的数组,每个数字都有一个索引。在存储桶排序中,您可以拥有1到20之间的数组,并在每个元素中包含类似链接列表的内容。因此,如果您放置数字109,它可能对应于索引10。

答案 2 :(得分:0)

您可以在此处使用基数排序。当你对输入有限制时,就像你的情况一样,它运作良好。在这里查看算法 - http://en.wikipedia.org/wiki/Radix_sort

答案 3 :(得分:0)

您可以使用基数排序,计数排序,有很多O(n)排序。

但问题是让你真的很容易......

在Java中:

int [n] input = {your list of n numbers}; int [2*n] listinorder; int [n] output;

for (int i=0, i<2n, i++) listinorder[i] = -1; // set all values of listinorder to -1

for (int i=0, i < n, i++) listinorder[input[i]] = input[i]; // set the ith value of listinorder to i

int j=0;

for (int i=0, i<2n, i++) if (listinorder(i)  != -1) {output[j] = i; j++};

英文:

  1. 建立一个长度为2n的数组(例如listinorder)。
  2. 将每个值设置为-1。逐步完成输入列表。
  3. 对于输入列表中的每个值i,设置相应的值 listinorder to i(即listinorder[i]=i)。然后一步一步 listinorder的值不是-1,以生成排序列表。
  4. 所有O(n)。