鲜花:详细揭秘:随机选点快速排序的期望复杂度

前言

中午在知乎上看见有人狗叫随机化快排随便卡。

为了科学打脸,我尝试证明了一下随机化快排的复杂度。

因为我是复杂度分析低手,所以下面的证明只有代数内容,不涉及任何复杂度分析理论。

正文

为了方便证明,我们设序列中的数互不相同。否则,我们可以钦定相同数之间的大小关系,使得它们互不相同。

为了尽量严谨,本文所说的随机选点快速排序,以这样一种流程进行:

  • 当区间长度 \(\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)\) 的,但是由于这是期望复杂度,所以常数巨大,在实际情况中根本看不出二者的区别。

代数推导部分经数竞同学检查,如仍有错误请指出。

posted @ 2025-01-22 19:32  _Kenma  阅读(100)  评论(4)    收藏  举报