Problem 2: Select the t t tth Largest (Knuth 论文第二题研讨)
1.问题背景
对给定的 n n n个数 x [ 1 ] , x [ 2 ] , ⋯ , x [ n ] x[1],x[2],\cdots,x[n] x[1],x[2],⋯,x[n],保证这 n n n个数互不相等,找到第 t t t大的数。 Hoare给出了这样一个通过反复比较来达成目标的一个算法:考虑快速排序中的思想,选择其中的任意一个元素 y y y,将它与其它 n − 1 n-1 n−1个数依次比较,随后将其放到第 k k k个位置,保证右边的数都比它小,左边的数都比它大,这样 y y y就保证了是第 k k k大的元素。(这里的左大右小和快速排序是相反的,但是可以方便表述。)
如果 k = t k=t k=t,就找到了第 t t t大的元素;
如果 k > t k>t k>t,则用同样的方法在 x [ 1 ] , ⋯ , x [ k − 1 ] x[1],\cdots,x[k-1] x[1],⋯,x[k−1]中找第 t t t大的元素;
如果 k < t k<t k<t,则用同样的方法在 x [ k + 1 ] , ⋯ , x [ n ] x[k+1],\cdots, x[n] x[k+1],⋯,x[n]中找第 ( t − k ) (t-k) (t−k)大的元素。
2.代码
int find(x, i, j, t){
int key = x[i];
k = Partition(x, i, j, key)- i + 1;
if(k == t) return a[k];
else if(k > t) return find(x, i, k - 1, t);
else return find(x, k + 1, j, t - k);
}
3.复杂度分析
令
C
(
n
,
t
)
C(n,t)
C(n,t)表示在
n
n
n个数中找第
t
t
t大的数的比较次数。那么最基本的有
C
(
1
,
1
)
=
0
C(1,1)=0
C(1,1)=0
寻找递推式:
若 k = 1 k=1 k=1, C ( n , t ) = n − 1 + C ( n − 1 , t − 1 ) C(n,t)=n-1+C(n-1,t-1) C(n,t)=n−1+C(n−1,t−1)
若 k = 2 , C ( n , t ) = n − 1 + C ( n − 2 , t − 2 ) k=2,C(n,t)=n-1+C(n-2,t-2) k=2,C(n,t)=n−1+C(n−2,t−2)
⋯ \cdots ⋯
若 k = t , C ( n , t ) = n − 1 k=t,C(n,t)=n-1 k=t,C(n,t)=n−1
若 k = t + 1 , C ( n , t ) = n − 1 + C ( t , t ) k=t+1,C(n,t)=n-1+C(t,t) k=t+1,C(n,t)=n−1+C(t,t)
⋯ \cdots ⋯
若 k = n , C ( n , t ) = n − 1 + C ( n − 1 , t ) k=n,C(n,t)=n-1+C(n-1,t) k=n,C(n,t)=n−1+C(n−1,t)
由于
k
k
k在每个位置出现的概率相等,将上述
n
n
n个式子相加求平均值即可得到
C
(
n
,
t
)
=
n
−
1
+
1
n
(
A
(
n
,
t
)
+
B
(
n
,
t
)
)
C(n,t)=n-1+\dfrac{1}{n}(A(n,t)+B(n,t))
C(n,t)=n−1+n1(A(n,t)+B(n,t))
其中:
A
(
n
,
t
)
=
C
(
n
−
1
,
t
−
1
)
+
⋯
+
C
(
n
−
t
+
1
,
1
)
B
(
n
,
t
)
=
C
(
t
,
t
)
+
C
(
t
+
1
,
t
)
+
⋯
+
C
(
n
−
1
,
t
)
A(n,t)=C(n-1,t-1)+\cdots+C(n-t+1,1)\\ B(n,t)=C(t,t)+C(t+1,t)+\cdots+C(n-1,t)
A(n,t)=C(n−1,t−1)+⋯+C(n−t+1,1)B(n,t)=C(t,t)+C(t+1,t)+⋯+C(n−1,t)
首先通过观察得到
A
(
n
+
1
,
t
+
1
)
=
A
(
n
,
t
)
+
C
(
n
,
t
)
B
(
n
+
1
,
t
+
1
)
=
B
(
n
,
t
)
+
C
(
n
,
t
)
A(n+1,t+1)=A(n,t)+C(n,t)\\ B(n+1,t+1)=B(n,t)+C(n,t)
A(n+1,t+1)=A(n,t)+C(n,t)B(n+1,t+1)=B(n,t)+C(n,t)
由上述式子,计算
(
n
+
1
)
C
(
n
+
1
,
t
+
1
)
−
n
C
(
n
,
t
+
1
)
−
n
C
(
n
,
t
)
+
(
n
−
1
)
C
(
n
−
1
,
t
)
(
带
入
上
述
等
式
)
=
2
+
C
(
n
,
t
)
−
2
C
(
n
−
1
,
t
)
+
C
(
n
,
t
+
1
)
(n+1)C(n+1,t+1)-nC(n,t+1)-nC(n,t)+(n-1)C(n-1,t)(带入上述等式)\\ =2+C(n,t)-2C(n-1,t)+C(n,t+1)
(n+1)C(n+1,t+1)−nC(n,t+1)−nC(n,t)+(n−1)C(n−1,t)(带入上述等式)=2+C(n,t)−2C(n−1,t)+C(n,t+1)
整理即得:
C
(
n
+
1
,
t
+
1
)
−
C
(
n
,
t
+
1
)
−
C
(
n
,
t
)
+
C
(
n
−
1
,
t
)
=
2
n
+
1
.
(
∗
)
C(n+1,t+1)-C(n,t+1)-C(n,t)+C(n-1,t)=\dfrac{2}{n+1}.\quad (*)
C(n+1,t+1)−C(n,t+1)−C(n,t)+C(n−1,t)=n+12.(∗)
由于上式隐含了条件 n ≥ t + 1 n\ge t+1 n≥t+1,由对称性, t t t有隐藏范围 1 < t < n 1<t<n 1<t<n。
对边界进行检查:考虑
t
=
1
t=1
t=1和
t
=
n
t=n
t=n的情况
C
(
n
,
1
)
=
n
−
1
+
1
n
(
C
(
1
,
1
)
+
C
(
2
,
1
)
+
⋯
+
C
(
n
−
1
,
1
)
)
(
1
)
C
(
n
+
1
,
1
)
=
n
+
1
n
+
1
(
C
(
1
,
1
)
+
C
(
2
,
1
)
+
⋯
+
C
(
n
,
1
)
)
(
2
)
(
2
)
∗
(
n
+
1
)
−
(
1
)
∗
n
:
C
(
n
+
1
,
1
)
−
C
(
n
,
1
)
=
2
−
2
n
+
1
C(n,1)=n-1+\dfrac{1}{n}(C(1,1)+C(2,1)+\cdots+C(n-1,1))\quad (1)\\ C(n+1,1)=n+\dfrac{1}{n+1}(C(1,1)+C(2,1)+\cdots+C(n,1))\quad (2)\\ (2)*(n+1)-(1)*n:\\ C(n+1,1)-C(n,1)=2-\dfrac{2}{n+1}
C(n,1)=n−1+n1(C(1,1)+C(2,1)+⋯+C(n−1,1))(1)C(n+1,1)=n+n+11(C(1,1)+C(2,1)+⋯+C(n,1))(2)(2)∗(n+1)−(1)∗n:C(n+1,1)−C(n,1)=2−n+12
因此累加即得
C
(
n
,
1
)
=
2
n
−
2
H
(
n
)
,
H
(
n
)
=
1
+
1
2
+
⋯
+
1
n
C(n,1)=2n-2H(n), H(n)=1+\dfrac{1}{2}+\cdots+\dfrac{1}{n}
C(n,1)=2n−2H(n),H(n)=1+21+⋯+n1
由对称性同理可得
C
(
n
,
n
)
=
C
(
n
,
1
)
=
2
n
−
H
(
n
)
C(n,n)=C(n,1)=2n-H(n)
C(n,n)=C(n,1)=2n−H(n)
再考虑
(
∗
)
(*)
(∗)式,将这个式子看作是关于
n
n
n的等式,依次将
n
n
n递减至
t
+
1
t+1
t+1,观察:
C
(
n
+
1
,
t
+
1
)
−
C
(
n
,
t
+
1
)
−
C
(
n
,
t
)
+
C
(
n
−
1
,
t
)
=
2
n
+
1
.
C
(
n
,
t
+
1
)
−
C
(
n
−
1
,
t
+
1
)
−
C
(
n
−
1
,
t
)
+
C
(
n
−
2
,
t
)
=
2
n
.
C
(
n
−
1
,
t
+
1
)
−
C
(
n
−
2
,
t
+
1
)
−
C
(
n
−
2
,
t
)
+
C
(
n
−
3
,
t
)
=
2
n
−
1
.
⋯
C
(
t
+
2
,
t
+
1
)
−
C
(
t
+
1
,
t
+
1
)
−
C
(
t
+
1
,
t
)
+
C
(
t
,
t
)
=
2
t
+
2
C(n+1,t+1)-C(n,t+1)-C(n,t)+C(n-1,t)=\dfrac{2}{n+1}.\\ C(n,t+1)-C(n-1,t+1)-C(n-1,t)+C(n-2,t)=\dfrac{2}{n}.\\ C(n-1,t+1)-C(n-2,t+1)-C(n-2,t)+C(n-3,t)=\dfrac{2}{n-1}.\\ \cdots\\ C(t+2,t+1)-C(t+1,t+1)-C(t+1,t)+C(t,t)=\dfrac{2}{t+2}
C(n+1,t+1)−C(n,t+1)−C(n,t)+C(n−1,t)=n+12.C(n,t+1)−C(n−1,t+1)−C(n−1,t)+C(n−2,t)=n2.C(n−1,t+1)−C(n−2,t+1)−C(n−2,t)+C(n−3,t)=n−12.⋯C(t+2,t+1)−C(t+1,t+1)−C(t+1,t)+C(t,t)=t+22
将上述所有等式相加即得:
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)&=\dfrac{2}{n+1}+\dfrac{2}{n}+\cdots+\dfrac{2}{t+2}+C(t+1,t+1)-C(t,t)\\ &=2(H(n+1)-H(t+1))+2-\dfrac{2}{t+1} \end{aligned}
C(n+1,t+1)−C(n,t)=n+12+n2+⋯+t+22+C(t+1,t+1)−C(t,t)=2(H(n+1)−H(t+1))+2−t+12
由这个迭代式即可求出
C
(
n
,
t
)
=
2
∑
2
≤
k
≤
t
(
H
(
n
−
t
+
k
)
−
H
(
k
)
+
1
−
1
k
)
+
C
(
n
+
1
−
t
,
1
)
=
2
(
(
n
+
1
)
H
(
n
)
−
(
n
+
3
−
t
)
H
(
n
+
1
−
t
)
−
(
t
+
2
)
H
(
t
)
+
3
+
n
)
\begin{aligned} C(n,t)&=2\sum_{2\le k\le t}(H(n-t+k)-H(k)+1-\dfrac{1}{k})+C(n+1-t,1)\\ &=2((n+1)H(n)-(n+3-t)H(n+1-t)-(t+2)H(t)+3+n) \end{aligned}
C(n,t)=22≤k≤t∑(H(n−t+k)−H(k)+1−k1)+C(n+1−t,1)=2((n+1)H(n)−(n+3−t)H(n+1−t)−(t+2)H(t)+3+n)
注意这一步要使用调和级数函数的一个求和公式:
∑
k
=
1
n
H
(
k
)
=
(
n
+
1
)
H
(
n
)
−
n
\sum_{k=1}^{n} H(k)=(n+1)H(n)-n
k=1∑nH(k)=(n+1)H(n)−n
因此,对于给定的 t t t, 这个比较次数是 O ( n ) O(n) O(n)的,比排序算法的 O ( n l o g n ) O(nlogn) O(nlogn)要快。