需要显示一个带有特殊分区的快速排序,其中一个数组被分成3个部分(<比3个pivot,=到pivot,>而不是pivot)和一个大小为N的特殊数组,其中只有7个不同的键可以在O(N)中排序。
所以,我想我们可以假设在中间的某个地方选择了枢轴(否则我们可能会有[0,1,2,3,4,5,6,6,6,6 ......] ..]那应该采取O(N ^ 2))。
这就是我的想法:
假设我们进行了第一次分区。现在我们转到递归步骤2.假设我们只关注正确的分区。由于此处的每个元素都大于枢轴,并且只有7个不同的键,因此该分区中不同键的数量严格小于7.这意味着在算法的7次迭代之后,左侧和右侧子中的所有元素-sub -...-分区应该是相同的。
现在,我可以看到如果算法停止在常量数组上重复出现,这将是O(N),但我的理解是它没有。如果不是这样的话,请澄清一下。
那么这里发生了什么?
答案 0 :(得分:2)
快速排序算法如下所示:
quicksort(A, lo, hi):
if lo < hi:
p := partition(A, lo, hi)
quicksort(A, lo, p - 1)
quicksort(A, p + 1, hi)
我们有一个3路的特殊分区,所以我们说它会为它选择的任何枢轴返回相等的范围,我们只需要低于和高于:
quicksort(A, lo, hi):
if lo < hi:
p1, p2 := 3-way-partition(A, lo, hi)
quicksort(A, lo, p1 - 1) // (1)
quicksort(A, p2 + 1, hi) // (2)
现在,考虑非常糟糕的情况。我们有一个看起来像[0,1,2,3,4,5,6,6,6,6...]
的数组,我们的枢轴选择算法尽可能愚蠢:它以严格递增的顺序选择枢轴。在这种情况下,第一次递归调用(上面的(1)
)将始终不执行任何操作,因为没有任何小于枢轴。因此,我们只处理一个大小为N - 1
的递归调用。
每次递归调用都会将问题大小减小一,直到第7次递归调用(将选择6
枢轴) - 完成排序。这是仅有7个不同键的关键步骤 - 您最多只需要7个呼叫。这7个调用中的每一个都会迭代整个数组... O(7N) == O(N)
。更一般地说,如果只有k
个不同的密钥,您可以说最坏的情况是来自同一个参数的O(kN)
。