你能以O(n)摊销的复杂性排序n个整数吗?

时间:2011-05-25 08:56:37

标签: algorithm complexity-theory big-o

理论上可以用O(n)的摊销复杂度对n个整数数组进行排序吗?

尝试创建O(n)复杂性的最坏情况怎么样?

今天的大多数算法都建立在O(nlogn)平均值+ O(n ^ 2)最坏的情况下。 有些人虽然使用更多内存,但O(nlogn)最差。

你对内存使用没有限制可以创建这样的算法吗? 如果你的记忆力有限怎么办?这将如何伤害你的算法?

4 个答案:

答案 0 :(得分:11)

intertubes上处理基于比较的排序will tell you的任何页面, 排序比O(n lg n)排序的速度快。也就是说,如果您的排序算法通过将2个元素相互比较来确定顺序,那么您不能做得更好。示例包括quicksort,bubblesort,mergesort。

某些算法(如计数排序或存储桶排序或基数排序)不使用比较。相反,它们依赖于数据本身的属性,例如数据中的值范围或数据值的大小。

那些算法可能具有更快的复杂性。以下是一个示例场景:

  

您正在排序10^6个整数,每个整数介于010之间。然后你可以只计算零,一,二等的数量,并按排序顺序吐出它们。这就是countort的工作原理,O(n + m)其中m是您的数据可以采用的值的数量(在这种情况下,m=11)。

另:

  

您正在排序长度最多为10^6个字符的5个二进制字符串。你可以使用基数排序:首先根据它们的第一个字符将它们分成2个桶,然后对第二个字符,第三个,第四个和第五个字符进行基数排序。只要每个步骤都是稳定的排序,您应该在O(nm)中得到一个完美排序的列表,其中m是数据中的数字或位数(在本例中为m=5)。

但是在一般情况下,您不能可靠地排序O(n lg n)(使用比较排序)。

答案 1 :(得分:4)

到目前为止,我对接受的答案并不满意。所以我正在重试一个答案:

  

理论上可以用O(n)的摊销复杂度对n个整数数组进行排序吗?

这个问题的答案取决于执行排序算法的机器。如果你有一个随机访问机器,它可以正好运行1位,你可以radix sort对最多k位的整数进行操作,这已经建议了。因此,您最终会遇到复杂性O(kn) 但是,如果您使用字大小至少为k位(所有消费者计算机都是)的固定大小的字机操作,那么您可以获得的最佳效果是O(n log n)。这是因为log n < k或者您可以首先执行count sort,然后使用O (n log n)算法排序,这也会产生第一种情况。

  

尝试创建O(n)复杂性的最坏情况怎么样?

这是不可能的。已经给出了一个链接。证明的想法是,为了能够进行排序,如果要对要排序的任何其他元素更大或更小,则必须决定要排序的每个元素。通过使用传递性,这可以表示为决策树,其最多具有n个节点和log n深度。因此,如果您希望性能优于Ω(n log n),则意味着从该决策树中删除边缘。但是,如果决策树不完整,那么您如何确保对某些元素ab做出了正确的决定?

  

你对内存使用没有限制可以创建这样的算法吗?

所以从上面来说这是不可能的。因此,剩下的问题无关紧要。

答案 2 :(得分:2)

如果整数在有限的范围内,那么它们的O(n)“排序”将涉及具有“n”位的位向量...在所讨论的整数上循环并设置n%8位将该字节数组中的偏移量n // 8设置为true。这是一个“O(n)”操作。列表/枚举/返回/打印所有设置位的该位数组上的另一个循环同样是O(n)操作。 (当然O(2n)被还原为O(n))。

这是一种特殊情况,其中n足够小以适合内存或文件(使用seek())操作)。这不是一般解决方案;但它在Bentley的“Programming Pearls”中得到了描述 - 并且据称是解决现实世界问题的实际解决方案(涉及类似电话号码的“freelist”......类似于:找到第一个可用的电话号码发给新订户。)

(注意:log(10 * 10)是~24位代表每个可能的长度,长度最多为10位...所以在2 * 31位的典型空间中有足够的空间Unix / Linux最大内存映射)。

答案 3 :(得分:0)

我相信您正在寻找radix sort