开头废话
这个问题是Donald.E.Knuth在他发表的论文Mathematical Analysis of Algorithms中提到的,这里对他的算法分析过程给出了更详细的解释。
问题描述:
给定一个数组a[1,2,…,n],用尽量少的比较次数找出数组中第t大的数。(假定这n个数两两不同)。
算法描述:
对于这个问题,可以很容易想到对应的算法。一个
O
(
n
log
n
)
O(n\log n)
O(nlogn) 的排序算法总能解决问题(然鹅今天我们并不对数组进行完全的排序)。
参照快速排序中的Partition操作,将元素a[i]放到某个位置
k
k
k,使得排在它前面的元素都比它大(但不一定按照从大到小的次序排列),后面的元素都比它小。再根据a[i]的位置
k
k
k与
t
t
t的大小关系,缩小查找范围再对子问题求解。
对于每一次Partition操作,会有这样的3种情况:
(1).若
k
=
t
k=t
k=t,算法结束。
(2).若
k
>
t
k>t
k>t,则对a[i]~a[k-1]递归地求解
(3).若
k
<
t
k<t
k<t,则对a[k+1]~a[j]递归地求解
时间复杂度分析
在这个问题的求解过程中,产生子问题的规模不断缩小。其中影响子问题的变量有 n n n(数组的长度)和 t t t(待查找的t)。Knuth记 C n , t C_{n,t} Cn,t为在 n n n个元素的数组中选择第 t t t大的数所需的平均比较次数,这里有一个前提,我们假设数组的排列是随机的,每一次Partition找到第1,第2,…,第n大的数概率均为 1 n \frac 1 n n1。
于是我们可以得到这样的式子:
C
1
,
1
=
0
C
n
,
t
=
n
−
1
+
1
n
(
A
n
,
t
+
B
n
,
t
+
0
)
\begin {aligned} C_{1,1}&=0\\ C_{n,t}&=n-1+\frac 1n (A_{n,t}+B_{n,t}+0) \end {aligned}
C1,1Cn,t=0=n−1+n1(An,t+Bn,t+0)其中
A
n
,
t
A_{n,t}
An,t和
B
n
,
t
B_{n,t}
Bn,t的定义如下:
A
n
,
t
=
C
n
−
1
,
t
−
1
+
C
n
−
2
,
t
−
2
+
⋯
+
C
n
−
t
+
1
,
1
B
n
,
t
=
C
t
,
t
+
C
t
+
1
,
t
+
⋯
+
C
n
−
1
,
t
\begin {aligned} A_{n,t}&=C_{n-1,t-1}+C_{n-2,t-2}+\cdots+C_{n-t+1,1}\\ B_{n,t}&=C_{t,t}+C_{t+1,t}+\cdots+C_{n-1,t} \end {aligned}
An,tBn,t=Cn−1,t−1+Cn−2,t−2+⋯+Cn−t+1,1=Ct,t+Ct+1,t+⋯+Cn−1,t这里
A
n
,
t
A_{n,t}
An,t对应的是递归过程中所有
k
<
t
k<t
k<t的情况。对于这些情况,我们从数组的第
k
+
1
k+1
k+1项开始向后的部分进行求解,如果把这部分看作一个新的数组,那么原始数组中第
t
t
t大的数,在新的数组中是第
t
−
k
t-k
t−k大的,也就是说这部分子问题是查找长度为
n
−
k
n-k
n−k的数组中第
t
−
k
t-k
t−k大的元素,其中
1
≤
k
≤
n
.
1\leq k \leq n.
1≤k≤n.
类似的, B n , t B_{n,t} Bn,t对应所有 k > t k>t k>t的情况,将数组第一项到第 k − 1 k-1 k−1项取出,看作一个新的数组,原始数组中第 t t t大的数,在这新的数组中仍然是第 t t t大,所以这部分的子问题是在长度为 k − 1 k-1 k−1的数组中选择第 t t t大的数,其中 t + 1 ≤ k ≤ n . t+1\leq k \leq n. t+1≤k≤n.
括号内剩下的一项 0 0 0,对应的是 k = t k=t k=t的情况,因为此时算法结束,不需要再求解子问题,所以比较次数为 0. 0. 0.括号外的 n − 1 n-1 n−1是一次Partition要进行的比较次数。
这样,括号内就等于所有可能规模子问题的比较次数的总和,将它乘以 1 n \frac 1n n1,就得到子问题比较次数的数学期望,即我们所求的平均情况下的预期比较次数。
通过观察我们可以得到以下的递推公式:
A
n
+
1
,
t
+
1
=
C
n
−
1
,
t
−
1
+
C
n
−
2
,
t
−
2
+
⋯
+
C
n
−
t
+
1
,
1
+
C
n
,
t
=
A
n
,
t
+
C
n
,
t
B
n
+
1
,
t
=
C
t
,
t
+
C
t
+
1
,
t
+
⋯
+
C
n
−
1
,
t
+
C
n
+
1
−
1
,
t
=
B
n
,
t
+
C
n
,
t
\begin {aligned} A_{n+1,t+1}&=C_{n-1,t-1}+C_{n-2,t-2}+\cdots+C_{n-t+1,1}+C_{n,t}=A_{n,t}+C_{n,t}\\ B_{n+1,t}&=C_{t,t}+C_{t+1,t}+\cdots+C_{n-1,t}+C_{n+1-1,t}=B_{n,t}+C_{n,t} \end{aligned}
An+1,t+1Bn+1,t=Cn−1,t−1+Cn−2,t−2+⋯+Cn−t+1,1+Cn,t=An,t+Cn,t=Ct,t+Ct+1,t+⋯+Cn−1,t+Cn+1−1,t=Bn,t+Cn,t由上述等式作差消法,可以得到:
(
n
+
1
)
C
n
+
1
,
t
+
1
−
n
C
n
,
t
+
1
−
n
C
n
,
t
+
(
n
−
1
)
C
n
−
1
,
t
=
(
n
+
1
)
n
−
n
(
n
−
1
)
−
n
(
n
−
1
)
+
(
n
−
1
)
(
n
−
2
)
+
(
A
n
+
1
,
t
+
1
−
A
n
,
t
)
−
(
A
n
,
t
+
1
−
A
n
−
1
,
t
)
+
(
B
n
+
1
,
t
+
1
−
B
n
,
t
+
1
)
−
(
B
n
,
t
−
B
n
−
1
,
t
)
=
2
+
C
n
,
t
−
C
n
−
1
,
t
+
C
n
,
t
+
1
−
C
n
−
1
,
t
(n+1)C_{n+1,t+1}-nC_{n,t+1}-nC_{n,t}+(n-1)C_{n-1,t}\\ =(n+1)n-n(n-1)-n(n-1)+(n-1)(n-2)\\+(A_{n+1,t+1}-A_{n,t})-(A_{n,t+1}-A_{n-1,t})+(B_{n+1,t+1}-B_{n,t+1})-(B_{n,t}-B_{n-1,t}) \\ =2+C_{n,t}-C_{n-1,t}+C_{n,t+1}-C_{n-1,t}
(n+1)Cn+1,t+1−nCn,t+1−nCn,t+(n−1)Cn−1,t=(n+1)n−n(n−1)−n(n−1)+(n−1)(n−2)+(An+1,t+1−An,t)−(An,t+1−An−1,t)+(Bn+1,t+1−Bn,t+1)−(Bn,t−Bn−1,t)=2+Cn,t−Cn−1,t+Cn,t+1−Cn−1,t合并同类项即可得到:
(
n
+
1
)
C
n
+
1
,
t
+
1
−
(
n
+
1
)
C
n
,
t
+
1
−
(
n
+
1
)
C
n
,
t
+
(
n
+
1
)
C
n
−
1
,
t
=
2
⇓
C
n
+
1
,
t
+
1
−
C
n
,
t
+
1
−
C
n
,
t
+
C
n
−
1
,
t
=
2
n
+
1
(n+1)C_{n+1,t+1}-(n+1)C_{n,t+1}-(n+1)C_{n,t}+(n+1)C_{n-1,t}=2\\\Downarrow\\ C_{n+1,t+1}-C_{n,t+1}-C_{n,t}+C_{n-1,t}=\frac{2}{n+1}
(n+1)Cn+1,t+1−(n+1)Cn,t+1−(n+1)Cn,t+(n+1)Cn−1,t=2⇓Cn+1,t+1−Cn,t+1−Cn,t+Cn−1,t=n+12
接下来我们考察边界条件,当
t
=
1
t=1
t=1时,由以上的式子我们可以得到下述方程组:
{
C
n
,
1
=
n
−
1
+
1
n
(
C
1
,
1
+
C
2
,
1
+
⋯
+
C
n
−
1
,
1
)
B
n
,
1
=
C
1
,
1
+
C
2
,
1
+
⋯
+
C
n
−
1
,
1
B
n
+
1
,
1
=
B
n
,
1
+
C
n
,
1
C
n
,
1
=
n
−
1
+
1
n
(
B
n
,
1
)
C
n
+
1
,
1
=
n
+
1
n
+
1
(
B
n
+
1
,
1
)
\left\{ \begin{array}{l} C_{n,1}= n-1+\frac{1}{n}(C_{1,1}+C_{2,1}+\cdots +C_{n-1,1})\\ B_{n,1}=C_{1,1}+C_{2,1}+\cdots+C_{n-1,1}\\ B_{n+1,1}=B_{n,1}+C_{n,1}\\ C_{n,1}=n-1+\frac{1}{n}(B_{n,1})\\ C_{n+1,1}=n+\frac{1}{n+1}(B_{n+1,1}) \end{array} \right.
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧Cn,1=n−1+n1(C1,1+C2,1+⋯+Cn−1,1)Bn,1=C1,1+C2,1+⋯+Cn−1,1Bn+1,1=Bn,1+Cn,1Cn,1=n−1+n1(Bn,1)Cn+1,1=n+n+11(Bn+1,1)消去方程组中包含
B
B
B的项,可以得到:
(
n
+
1
)
C
n
+
1
,
1
−
n
C
n
,
1
=
(
n
+
1
)
n
−
n
(
n
−
1
)
+
C
n
,
1
C
n
+
1
,
1
−
C
n
,
1
=
2
−
2
n
+
1
(
∗
)
\begin{aligned} (n+1)C_{n+1,1}-nC_{n,1} &= (n+1)n-n(n-1)+C_{n,1}\\ C_{n+1,1}-C_{n,1}&=2-\frac{2}{n+1} \quad\quad(*) \end{aligned}
(n+1)Cn+1,1−nCn,1Cn+1,1−Cn,1=(n+1)n−n(n−1)+Cn,1=2−n+12(∗)接下来求解
C
n
,
1
C_{n,1}
Cn,1:
列出方程组:
{
C
1
,
1
=
0
C
2
,
1
−
C
1
,
1
=
2
−
2
2
C
3
,
1
−
C
2
,
1
=
2
−
2
3
⋯
C
n
,
1
−
C
n
−
1
,
1
=
2
−
2
n
\left\{ \begin{array}{c} \begin{aligned} C_{1,1}&=0\\ C_{2,1}-C_{1,1}&=2-\frac22\\ C_{3,1}-C_{2,1}&=2-\frac23\\ \cdots\\ C_{n,1}-C_{n-1,1}&=2-\frac2n\\ \end{aligned} \end{array} \right.\\
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧C1,1C2,1−C1,1C3,1−C2,1⋯Cn,1−Cn−1,1=0=2−22=2−32=2−n2将以上
n
n
n个方程求和,最终左边只剩下
C
n
,
1
C_{n,1}
Cn,1,得到如下式子:
C
n
,
1
=
2
(
n
−
1
)
−
2
∑
k
=
2
n
1
k
⇓
C
n
,
1
=
2
n
−
2
∑
k
=
1
n
1
k
=
2
n
−
2
H
n
\begin{aligned} C_{n,1}&=2(n-1)-2\sum_{k=2}^n \frac1k\\ \quad\Downarrow \\ C_{n,1}&=2n-2\sum_{k=1}^n\frac1k=2n-2H_n \end{aligned}
Cn,1⇓Cn,1=2(n−1)−2k=2∑nk1=2n−2k=1∑nk1=2n−2Hn这里的
H
n
H_n
Hn表示调和级数的前
n
n
n项部分和。
由于问题具有的对称性(这部分可自行证明),
C
n
,
n
=
C
n
,
1
=
2
n
−
2
H
n
C_{n,n}=C_{n,1}=2n-2H_n
Cn,n=Cn,1=2n−2Hn,将此式记作
(
Δ
)
(\Delta)
(Δ)
由
(
∗
)
(*)
(∗)式,可以列出以下方程组:
{
(
C
n
+
1
,
t
+
1
−
C
n
,
t
)
−
(
C
n
,
t
+
1
−
C
n
−
1
,
t
)
=
2
n
+
1
(
C
n
,
t
+
1
−
C
n
−
1
,
t
)
−
(
C
n
−
1
,
t
+
1
−
C
n
−
2
,
t
)
=
2
n
⋯
(
C
t
+
2
,
t
+
1
−
C
t
+
1
,
t
)
−
(
C
t
+
1
,
t
+
1
−
C
t
,
t
)
=
2
t
+
2
\left\{ \begin{array}{l} (C_{n+1,t+1}-C_{n,t})-(C_{n,t+1}-C_{n-1,t})=\frac2{n+1}\\ (C_{n,t+1}-C_{n-1,t})-(C_{n-1,t+1}-C_{n-2,t})=\frac2{n}\\ \quad\quad\quad\quad\quad\quad\quad\quad\cdots\\ (C_{t+2,t+1}-C_{t+1,t})-(C_{t+1,t+1}-C_{t,t})=\frac2{t+2}\\ \end{array} \right.\\
⎩⎪⎪⎨⎪⎪⎧(Cn+1,t+1−Cn,t)−(Cn,t+1−Cn−1,t)=n+12(Cn,t+1−Cn−1,t)−(Cn−1,t+1−Cn−2,t)=n2⋯(Ct+2,t+1−Ct+1,t)−(Ct+1,t+1−Ct,t)=t+22再次对这
n
−
t
n-t
n−t个方程累加,并联立
(
Δ
)
(\Delta)
(Δ)式,可以得到:
C
n
+
1
,
t
+
1
−
C
n
,
t
=
2
n
+
1
+
2
n
+
⋯
+
2
t
+
2
+
C
t
+
1
,
t
+
1
−
C
t
,
t
=
2
(
H
n
+
1
−
H
t
+
1
)
+
2
−
2
t
+
1
\begin{aligned} C_{n+1,t+1}-C_{n,t}&=\frac{2}{n+1}+\frac{2}{n}+\cdots+\frac{2}{t+2}+C_{t+1,t+1}-C_{t,t}\\ &=2(H_{n+1}-H_{t+1})+2-\frac{2}{t+1} \end{aligned}
Cn+1,t+1−Cn,t=n+12+n2+⋯+t+22+Ct+1,t+1−Ct,t=2(Hn+1−Ht+1)+2−t+12依次写出
C
n
,
t
−
C
n
−
1
,
t
−
1
C_{n,t}-C_{n-1,t-1}
Cn,t−Cn−1,t−1到
C
2
,
2
−
C
1
,
1
C_{2,2}-C_{1,1}
C2,2−C1,1的
n
−
1
n-1
n−1个方程并再次累加(过程略去),可以推出:
C
n
,
t
=
2
∑
2
≤
k
≤
t
(
H
n
−
t
+
k
−
H
k
+
1
−
1
k
)
+
C
n
+
1
−
t
,
1
C_{n,t}=2\sum_{2\leq k\leq t}(H_{n-t+k}-H_{k}+1-\frac1k)+C_{n+1-t,1}
Cn,t=22≤k≤t∑(Hn−t+k−Hk+1−k1)+Cn+1−t,1
化简后:
C
n
,
t
=
2
(
(
n
+
1
)
H
n
−
(
n
+
3
−
t
)
H
n
+
1
−
t
−
(
t
+
2
)
H
t
+
n
+
3
)
,
(
1
≤
t
≤
n
)
C_{n,t}=2((n+1)H_n-(n+3-t)H_{n+1-t}-(t+2)H_t+n+3),\quad(1\leq t\leq n)
Cn,t=2((n+1)Hn−(n+3−t)Hn+1−t−(t+2)Ht+n+3),(1≤t≤n)
由于
t
t
t与
n
n
n同阶,且平均情况下
t
t
t的数学期望
E
(
t
)
=
2
n
E(t)=\frac 2n
E(t)=n2,又
H
n
=
Θ
(
log
n
)
H_n=\Theta(\log n)
Hn=Θ(logn) ,所以:
C
n
,
t
=
O
(
n
log
n
)
C_{n,t}=O(n\log n)
Cn,t=O(nlogn)至此,时间复杂度的证明结束。