分治算法解决一个最坏O(N)时间的选择问题

分治算法的一个基础定理如下

定理1:若\sum_{i=1}^{k}a_{i}<1,则方程T(N)=\sum_{i=1}^{k}T(a_{i}N)+O(N)的解是T(N)=O(N)

意思是,把原问题分解成若干子问题,若这些子问题的规模之和没有原问题大,那么再加上处理这些子问题的O(N)时间,算法的时间界是O(N)

选择问题:在N个数中抽取第k小的,有几种解法:

1.可以用优先队列得到一个O(klogN)或者O(Nlogk)的时间,若k是中位数那么时间就是O(NlogN)

2.可以使用快速选择算法,每次处理一个不到原问题的子问题和线性附加时间,平均时间O(N),但是无法保证枢纽元的坏选择,因此最坏时间是O(N^2)

3.先将元素排序,自然可以得到第k小的数字,时间是O(NlogN)

以上几种解法中,快速选择算法在实践中应用最好,但是仍然无法达到O(N)最坏时间,根本原因是枢纽元的选择无法保证定理1成立。一般枢纽元的选择是三数中值法,但是若3个数都是最大元,那么是坏选择;可以增加使用的数字数量,用常数时间排序,得到中位数,由于按照定理1只能有常数附加时间,因此使用的数字个数最多可以达到O(\frac{N}{logN}),对其进行排序,花费时间O(N),显然不能超过这个数字,否则附加时间会超过O(N)。然而,在最坏情况下,还是不行,因为可能选择到O(\frac{N}{logN})个最大的元素,那么枢纽元是第O(N-\frac{N}{logN})个元素,每次处理的子问题是O(N-\frac{N}{logN}),这不是N的常数部分,无法应用定理1

五分化中项的中项:改进枢纽元选择如下:

1.把N个元素分成\left \lfloor N/5 \right \rfloor组,5个元素一组,剩余不到5个的一组可以忽略

2.找出每组的中项,得到\left \lfloor N/5 \right \rfloor个中项的表M

3.求出M的中项,将其作为枢纽元返回

定理2:使用五分化中项的中项进行枢纽元选择,快速选择算法最坏时间O(N)

证明:

N=10k+5,可以这样假设不影响时间界的计算,如下图:

其中,每一列是5个元素的一组,中间的格子是5个元素的中项,第三行就是所有中项,所有中项的中项用Mid表示,一共2k+1组,显然有k组中,每组有3个元素比Mid大,一共3k个元素,Mid自己所在的组有2个比Mid大,一共3k+2个一定比Mid大的,比Mid小的数字数量同理,这样每次处理的子问题大小最大可以达到0.7N,就是原问题的0.7倍。

到这里得到了子问题最坏的大小,还有两项附加工作要做:

1.在每个组中,在5个元素中选择中项花费时间是常数,所有组就是O(N)时间

2.在0.2N个中项中选择中项,若用排序,那么需要O(NlogN)时间,显然不行,因此需要对这些数字递归调用选择算法

综上,一次递归调用,解决0.7N大小和0.2N大小的两个子问题,加上O(N)线性时间,满足定理1要求,得到一个O(N)的最坏时间

猜你喜欢

转载自blog.csdn.net/kdb_viewer/article/details/83141435