如果我有一个大小为n的列表,并且我知道列表中的数字将在1到2n之间,那么在最坏的情况是O(n)的情况下,我将如何解决它?
我在想,如果它介于1和n之间,我可以取数字并将其与该数字的数值交换 - 1然后如果有任何重复则不会排序。
我在考虑类似的方法,列表中的数字介于1和2n之间,但我似乎无法弄明白。有什么帮助吗?
答案 0 :(得分:6)
Counting Sort 可以在 O(n)中运行。看看维基百科的定义
计数排序是一种用于对对象集合进行排序的算法 根据小整数的键;也就是说,它是一个整数 排序算法。它通过计算对象的数量来操作 拥有每个不同的键值,并使用这些计数的算术 确定输出序列中每个键值的位置。它的 运行时间与项目数量和差异呈线性关系 最大和最小键值之间,所以它只适合 直接用于键的变化不是的情况 显着大于项目数
答案 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++};
英文:
listinorder[i]=i
)。然后一步一步
listinorder的值不是-1,以生成排序列表。所有O(n)。