算法导论读书笔记(9)
选择问题
在一个由 n 个元素组成的集合中,第 i 个 顺序统计量 (order statistic)是该集合中第 i 小的元素。例如,在一组元素所组成的集合中, 最小值 是第 1 个顺序统计量( i = 1 ), 最大值 是第 n 个顺序统计量( i = n )。而 中位数 (median)是它所在集合的“中点元素”。像这样从一个由 n 个不同数值构成的集合中选择其第 i 个顺序统计量的问题,可以形式化地定义为 选择问题 (selection problem):
输入: 一个包含 n 个(不同的)数的集合 A 和一个数 i ,1 <= i <= n 。
输出: 元素 x ∈ A ,它恰好大于 A 中其他的 i - 1个元素。
最小值和最大值
MINIMUM(A) 1 min = A[1] 2 for i = 2 to A.length 3 if min > A[i] 4 min = A[i] 5 return min
MAXIMUM(A) 1 max = A[1] 2 for i = 2 to A.length 3 if max < A[i] 4 max = A[i] 5 reutrn max
对于上面两个过程来说,只要比较 n - 1次就能找出最大值/最小值。
随机选择算法
一般选择问题看起来要比找最小值的简单选择问题更难,但两种问题的渐近运行时间却是相同的:都是 Θ ( n )。这里介绍一种解决选择问题的分治算法,即 RANDOMIZED-SELECT
算法。该算法利用了之前介绍的 RANDOMIZED-PARTITION
过程。
RANDOMIZED-SELECT(A, p, r, i) 1 if p == r 2 return A[p] 3 q = RANDOMIZED-PARTITION(A, p, r) 4 k = q - p + 1 5 if i == k // the pivot value is the answer 6 return A[k] 7 elseif i < k 8 return RANDOMIZED-SELECT(A, p, q - 1, i) 9 else 10 return RANDOMIZED-SELECT(A, q + 1, r, i - k)
随机选择算法的最坏情况运行时间为 Θ ( n2 )。
最坏情况线性时间的选择
现在来看一个最坏情况运行时间为 Θ ( n )的选择算法 SELECT
。像 RANDOMIZED-SELECT
一样, SELECT
通过对输入数组的递归划分来找出所求元素。但是,该算法的基本思想是要保证对数组的划分是个好的划分。 SELECT
采用了取自快速排序的确定性划分算法 PARTITION
,并做了修改,把划分主元元素作为其参数。
算法 SELECT
通过执行下列步骤来确定一个有 n > 1个元素的输入数组中的第 i 小的元素。
- 将输入数组的 n 个元素划分成
FLOOR(n / 5)
组,每组5个元素,且至多只有一个组由剩下的 n mod 5个元素组成。 - 寻找
CEIL(n / 5)
个组中每一组的中位数。首先对每组中的元素(至多为5个)进行插入排序,然后从排序过的序列中选出中位数。 - 对第 2 步中找出的
CEIL(n / 5)
个中位数,递归调用SELECT
以找出其中位数 x 。 - 利用修改过的
PARTITION
过程,按中位数的中位数 x 对输入数组进行划分。让 k 比划分低区的元素数目多1,所以 x 是第 k 小的元素,并且有 n - k 个元素在划分的高区。 - 如果 i = k ,则返回 x 。否则,如果 i < k ,则在低区递归调用
SELECT
以找出第 i 小的元素,如果 i > k ,则在高区找出第 i - k 个最小元素。