理论上可以用O(n)的摊销复杂度对n个整数数组进行排序吗?
尝试创建O(n)复杂性的最坏情况怎么样?
今天的大多数算法都建立在O(nlogn)平均值+ O(n ^ 2)最坏的情况下。 有些人虽然使用更多内存,但O(nlogn)最差。
你对内存使用没有限制可以创建这样的算法吗? 如果你的记忆力有限怎么办?这将如何伤害你的算法?
答案 0 :(得分:11)
intertubes上处理基于比较的排序will tell you的任何页面, 排序比O(n lg n)
排序的速度快。也就是说,如果您的排序算法通过将2个元素相互比较来确定顺序,那么您不能做得更好。示例包括quicksort,bubblesort,mergesort。
某些算法(如计数排序或存储桶排序或基数排序)不使用比较。相反,它们依赖于数据本身的属性,例如数据中的值范围或数据值的大小。
那些算法可能具有更快的复杂性。以下是一个示例场景:
您正在排序
10^6
个整数,每个整数介于0
和10
之间。然后你可以只计算零,一,二等的数量,并按排序顺序吐出它们。这就是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)
,则意味着从该决策树中删除边缘。但是,如果决策树不完整,那么您如何确保对某些元素a
和b
做出了正确的决定?
你对内存使用没有限制可以创建这样的算法吗?
所以从上面来说这是不可能的。因此,剩下的问题无关紧要。
答案 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。