眾所周知,快速排序的時間復雜度為\(O(n\text{lg}n)\)。雖然對此很容易直觀理解,但由於算法的隨機特性,這一時間復雜度的嚴格證明並非顯然的。我將在這里說明如何計算快速排序運行過程中的比較次數的期望,以此得到對時間復雜度的較為嚴謹的證明。
定義\(E(n)\)為對長度為\(n\)的數組進行排序所需要的期望比較次數。考慮算法的划分過程,由於基准元素選擇的隨機性,每一種划分結果的可能性是相等的。對每種情況下的比較次數取平均值,即可得到下面的遞推式:$$E(n)=\frac{1}{n-1}\sum_{k=1}^{n-1} \left [E(k)+E(n-k)+n \right ]$$變量\(k\)枚舉了不同的划分情況,\(n\)表示划分過程中的比較次數。\(E(0)=E(1)=0\),因為空數組或只有一個元素的數組不需要比較。
得出遞推式后,剩下的就是數學推導了qwq
首先,我們注意到方括號里的\(n\)可以從求和符號里提取出來,而另外兩項是對稱的。於是等式可以改寫成下面的形式:
\[E(n)=n+\frac{2}{n-1}\sum_{k=1}^{n-1} E(k) \]
等式中包含太多項。注意右側的前綴求和形式,我們可以定義前綴和\(s(n)=\sum_{k=1}^{n} E(k)\)。等式再度簡化:
\[s(n)-s(n-1)=n+\frac{2}{n-1}s(n-1) \]
整理得到:
\[s(n)=n+\frac{n+1}{n-1}s(n-1) \]
等號兩邊同時除以\(n(n+1)\),得到
\[\frac{s(n)}{n(n+1)}=\frac{1}{n+1}+\frac{s(n-1)}{(n-1)n} \]
再做個換元,令
\[t(n)=\frac{s(n)}{n(n+1)} \]
局面頓時明了起來:
\[t(n)=t(n-1)+\frac{1}{n+1} \]
反復運用這一遞推式得到
\[t(n)=\frac{1}{3}+\frac{1}{4}+\frac{1}{5}+\cdots+\frac{1}{n}+\frac{1}{n+1} \]
這就是我們很熟悉的東西啦。讓我們把調和級數的前\(n\)項和記作\(H_n\),\(t(n)\)就可以寫成這樣的形式:
\[t(n)=H_{n+1}-\frac{3}{2} \]
接下來事情就順理成章了:
\[\begin{align} &s(n)=n(n+1)t(n)=n(n+1)\left(H_{n+1}-\frac{3}{2}\right) \notag \\&E(n)=s(n)-s(n-1)\notag \\&\;\;\;\;\;\;\;\;\:=n[(n+1)H_{n+1}-(n-1)H_n-3]\notag \\&\;\;\;\;\;\;\;\;\:=n(\frac{n}{n+1}+H_{n+1}+H_n-3)\notag \\&\;\;\;\;\;\;\;\;\:=n\left[\frac{n}{n+1}+(H_{n}+\frac{1}{n+1})+H_n-3\right]\notag \\&\;\;\;\;\;\;\;\;\:=2n(H_n-1)\notag \\&\;\;\;\;\;\;\;\;\:=2n\left[\int_{1}^{n}\frac{1}{x}dx+O(1)\right]\notag \\&\;\;\;\;\;\;\;\;\:=2n\left[\text{ln}n+O(1)\right]\notag \\&\;\;\;\;\;\;\;\;\:=O(n\text{lg}n)\notag \end{align}\]
\(Q.E.D.\;\;\;\;\;(\text{Quite Easily Done})\)