鲜花:详细揭秘:随机选点快速排序的期望复杂度
前言
中午在知乎上看见有人狗叫随机化快排随便卡。
为了科学打脸,我尝试证明了一下随机化快排的复杂度。
因为我是复杂度分析低手,所以下面的证明只有代数内容,不涉及任何复杂度分析理论。
正文
为了方便证明,我们设序列中的数互不相同。否则,我们可以钦定相同数之间的大小关系,使得它们互不相同。
为了尽量严谨,本文所说的随机选点快速排序,以这样一种流程进行:
-
当区间长度 \(\le 1\) 时,返回。否则,在目前的排序区间随机选择一个下标;
-
将小于这个值的元素放在选定下标的左侧,大于这个值的元素放在选定下标的右侧;
-
递归处理左右区间。
我们设 \(f_i\) 表示区间长度为 \(i\) 时,所需要的比较次数。因为序列中元素互不相同,所以 \(f_i\) 只和序列长度有关。
根据算法流程,对于 \(f\),我们有:
\[f_0=f_1=0
\]
\[f_n=n-1+\frac{1}{n}\sum_{i=0}^{n-1} f_i+f_{n-i-1}
\]
对于第二个式子,整理一下:
\[f_n=n-1+\frac{2}{n}\sum_{i=0}^{n-1} f_i
\]
现在问题转化为了分析 \(f_n\) 的复杂度量级。
尝试把 \(f_n\) 化为和式。
首先把分式消去:
\[nf_n=n^2-n+2\sum_{i=0}^{n-1} f_i
\]
然后仿照 \(f_n\),列出 \(f_{n-1}\) 的递推式:
\[(n-1)f_{n-1}=(n-1)^2-n+1+2\sum_{i=0}^{n-2} f_i
\]
两式做差:
\[nf_n=(n+1)f_{n-1}+2(n-1)
\]
然后把递归式化作和式:
\[f_n=(n+2)\sum_{i=1}^{n} \frac{1}{i+1} -\frac{2}{3}(n-1)
\]
注意到我们想要的形式出现了!
不妨设:
\[g_n=\sum_{i=1}^{n} \frac{1}{i}
\]
则有:
\[f_n=2(n+1)g_n-\frac{8}{3}(n+1)
\]
根据经典结论,\(g_n\) 是 \(O(\ln n)\) 量级的,所以 \(f_n\) 是 \(O(n \ln n)\) 量级的。
所以,随机选点快速排序的复杂度量级不是符合直觉的 \(O(n \log n)\),而是 \(O(n \ln n)\) 的,但是由于这是期望复杂度,所以常数巨大,在实际情况中根本看不出二者的区别。
代数推导部分经数竞同学检查,如仍有错误请指出。

浙公网安备 33010602011771号