上篇博客我们分析了RS算法的复杂度。我们发现只要我们选择的pivot足够好,该算法的平均复杂度是线性的。那么我们就会考虑,我们有没有办法改进一下RS呢,让我们的算法的复杂度就是。于是就有了今天要讨论的这个算法D-RS。
其实D-RS算法核心就是改进了RS算法的pivot的选择方式,保证了我们每一次都能选择到足够好的一个pivot。
老规矩,我们先给出D-RS算法的流程:
1. 先将数组分成5个元素一组,共计n/5个小组。
2. 对这n/5个小组进行排序,并求出其对应的中位数,, k代表第k个小组
3. 选出上述n/5 个中位数的中位数,这一步可以迭代使用RS( ,n/5, median)算法,为了方便我们用代表,作为我们的最终的pivot
4. 将原数组根据分成两部分,一部分都比小,另一部分都比大,同时假设第一部分得元素个数为j-1。
5. if j>i, return RS(1st part of A, j-1, i);
6 if j<i, return RS(2nd part of A, n-j, i-j);
7. if j=i, return p
可以看到,相较于RS算法,D-RS算法就是多了1-3步,主要就是给出了一种确定性方法挑选pivot。 首先第2步中,我们对长度为5得数组排序等操作都能再常数时间内完成,因此复杂都为,由于有n/5个这样得组,因此消耗得复杂度都为。和第4步得复杂度都保持一致。
而第3步由于递归调用RS算法,因此复杂度为。关键是第5步或者第6步得复杂度都为多少。
lemma 1:使用为pivot,第5或6步得输入规模至少下降30%,小于。
Proof: 我们可以将数组按如下方式排列:
我们可以看到,红色部分得元素都比要小,而蓝色部分得元素都比大,注意这里得中位数们都是按照升序排列过的。
绿色椭圆内元素得个数必然为,而红色部分,或者蓝色部分至少也有绿色部分得一半,即。因此,至少输入规模下降30%。
所以整体算法得复杂都为
这个复杂度得式子没办法直接使用master method,因此子任务规模不一样。因此,我们证明该复杂度式子是,数学归纳法。
n=1时,显然T(1)必然时常数。
设,n=k>1时, T(n) = cn。
,证毕。
到这里,我们也填上了快速排序那里得一个坑,即中位数能够再线性时间复杂度内找到,快速排序可以一定得到得复杂度。