Algorithm 对部分排序的数组进行排序

Algorithm 对部分排序的数组进行排序,algorithm,sorting,Algorithm,Sorting,可能重复: 我有一个部分排序的数组,其属性是每个元素都在其正确排序位置的d个单位内。我想知道是否有一种方法可以利用这个事实在不到n个logn的时间内对这个数组进行排序。是的。信不信由你,对于部分排序的数组,冒泡排序可能是最好的。最好的情况是完全排序的数组,在这种情况下,它的性能是O(n) 关于气泡排序的维基百科: 编辑:特别是“已修改的冒泡排序”,带有一个标记,用于在已排序时跳过交换。是;可以在O(nd)时间内进行排序。一种解决方案是对插入排序进行简单修改。我们从头到尾处理输入数组;对于每个元

可能重复:


我有一个部分排序的数组,其属性是每个元素都在其正确排序位置的d个单位内。我想知道是否有一种方法可以利用这个事实在不到n个logn的时间内对这个数组进行排序。

是的。信不信由你,对于部分排序的数组,冒泡排序可能是最好的。最好的情况是完全排序的数组,在这种情况下,它的性能是O(n)

关于气泡排序的维基百科:


编辑:特别是“已修改的冒泡排序”,带有一个标记,用于在已排序时跳过交换。

是;可以在O(nd)时间内进行排序。一种解决方案是对插入排序进行简单修改。我们从头到尾处理输入数组;对于每个元素,我们查看输出数组的最后d个元素,并将新元素插入其适当的位置


当然,可能有更快的算法;这种特殊的算法选择是为了更容易证明渐近界。

我相信(我想是哪种Python使用的?)正是这样做的。

在我的脑海里

创建一个尺寸为2d的“滑动窗口”

从[0,2d]开始。对窗口中的元素进行排序;现在确保元素0到d-1是正确的

将窗口向前滑动d,现在是[d,3d]。对这些元素进行排序,确保元素d到2d-1是正确的

再向前滑动一个d,现在是[2d,4d]。对它们进行排序。依此类推

每个排序都是O(d logd),需要n/d个步骤才能结束,所以这是O(n/d*d logd)=O(n logd)。如果d是常量,那就是O(n)

[编辑]

您在评论中提出了一个很好的观点;我没有证明每个迭代都保留了每个元素在其适当位置的d个单位内的属性

所以

引理:如果A是一个数组,其属性是每个元素都在其正确位置的d个单位内,并且您对A中的任何连续子序列进行排序以创建一个数组A',那么A'中的每个元素都在其正确位置的d个单位内

证明:因为这是一个关于排序属性的引理(不是性能),我们使用什么算法进行排序并不重要。因此,使用气泡排序。在子序列中找到任意两个无序的元素,并交换它们。只有三种情况:两个元素在数组中的正确位置之前;两个元素在数组中的正确位置之后;或者它们在arr中的正确位置之间嗯

例如,假设A[i]属于位置i',而A[j]属于位置j',iA[j],那么i'>j'(因为这是元素“属于”的地方,而A[i]>A[j])例1:假设i'和j'都大于i和j,也就是说,顺序是i
所以冒泡排序的每一步——在a的任何子序列上——都将保留所需的属性,从中可以看出整个冒泡排序将保留所需的属性,从中可以看出任何排序都将保留所需的属性这些自动考虑了部分排序。

作业?面试问题?或实际应用?(顺便说一下,问题不错。)这似乎与这个问题完全一致:“杰夫:太糟糕了。我有点喜欢我的答案:”插入排序可能是方法。我把它留给信息。也考虑使用一个冒泡排序并说它是有效率的,这是令人敬畏的。有没有一个地方,部分地优化了插入损耗的开源实现。rted数组?Timsort起源于Python,是一种自适应排序。仍然
O(nd)
,但要在
max 0(i-d)
min n(i+d)之间查找
我们不需要查看
i
之外的元素,因为我们还没有在那里插入任何元素。如果
i
属于
i+d
它将在以后插入时放在那里。谢谢。所有答案都很好,但是O(n log d)是我一直在寻找的边界。这个算法是否保留了每个元素必须始终在其正确排序位置的d个单位内的属性?@Schemer:这是一个很好的问题。我已经更新了我的答案。