该算法假设数组中没有重复元素。
预处理:
找到中位数元素,并以该元素为枢轴对数组进行划分。然后在较小的一半数组上不断应用此过程,直到剩下一个元素。
每个步骤中的较大一半数组称为 A(m), A(m-1), ...., A(0),其中 m 为某个值。A(0) 的大小始终为 1,每个连续数组要么是前一个数组的两倍大小,要么是前一个数组大小加一。即 len(A(0)) = 1,len(A(n)) = len(A(n-1)) 或 len(A(n-1))+1。注意,2^n ≤ len(A(n)) < 2^(n+1)。
对长度为 n 的数组查找中位数需要 O(n) 时间(使用众所周知的线性时间中位数查找算法),并且枢轴操作也需要 O(n) 时间。您在较小的一侧递归地应用此过程,总共需要 n + n/2 + n/4 + ... = O(n) 时间。
查找第 k 个元素:
定义 S(n) 为 A(0), A(1), ..., A(n-1) 长度之和。(S(0) = 0)。
找到 n,使得 S(n) ≤ k,且 S(n+1) > k。这可以在 O(log k) 时间内完成。
然后,在 A(n) 中找到第 k-S(n) 大的元素。使用(确定性变体的)quickselect 算法可以在 O(len(A(n))) 时间内完成。由于 len(A(n)) 是 Theta(k),因此该元素可以在 O(log k) + O(k) = O(k) 时间内找到。
理解提示:
首先考虑 n 为 2 的幂减一的情况。然后子数组 A(i) 的大小加倍。例如,当 n 为 16 时,输入是某些顺序的数字 0 到 15,子数组可能如下所示:
A(0) = [0]
A(1) = [2, 1]
A(2) = [6, 3, 4, 5]
A(3) = [15, 8, 11, 10, 7, 12, 13, 9, 14]
为了找到第7大的元素,我们发现它必须位于A(2)中,并且在A(0)和A(1)中组合了3个元素,因此我们需要在A(2)中找到第7-3 = 4大的元素。为此,我们使用快速选择算法。
build O(n)
是什么意思?预处理时间? - MBo