分类目录:《算法设计与分析》总目录
相关文章:
· 顺序统计量:最大值与最小值
· 顺序统计量:期望为线性时间的选择算法
· 顺序统计量:最坏情况为线性时间的选择算法
选择算法指的是在一个长度为 n n n的数列中找到第 i i i小或第 i i i大的元素。一般选择问题看起来要比找最小值这样的简单问题更难。但令人惊奇的是,这两个问题的渐近运行时间却是相同的: Θ ( n ) \Theta(n) Θ(n)。本文将介绍一种解决选择问题的分治算法。
randomized_select(arr, low, high, i)
算法是以《排序算法:快速排序-[基础知识]》中的快速排序算法为模型的。与快速排序一样,我们仍然将输入数组进行递归划分。但与快速排序不同的是,快速排序会递归处理划分的两边,而randomized_select(arr, low, high, i)
只处理划分的一边。这一差异会在性能分析中体现出来:快速排序的期望运行时间
Θ
(
n
lg
n
)
\Theta(n\lg n)
Θ(nlgn),而randomized_select(arr, low, high, i)
的期望运行时间为
Θ
(
n
)
\Theta(n)
Θ(n)。这里,假设输入数据都是互异的。
randomized_select(arr, low, high, i)
利用了《排序算法:快速排序-[快速排序的随机化]》介绍的randomized_partition(arr,low,high)
过程。与随机化的快速排序一样,因为它的部分行为是由随机数生成器的输出决定的,所以randomized_select(arr, low, high, i)
也是一个随机算法。以下是randomized_select(arr, low, high, i)
的代码,它返回数组arr
中第i
小的元素:
def randomized_select(arr, low, high, i):
if low == high:
return arr[low]
q = randomized_partition(arr,low,high)
k = q - low + 1
if i == k:
return arr[q]
elif i < k:
return randomized_select(arr, low, q - 1, i)
else:
return randomized_select(arr, q + 1, high, i)
randomized_partition(arr,low,high)
的运行过程如下:第2行检查递归的基本情况,即arr
中只包括一个元素。在这种情况下,i
必然等于1,在第3行,我们只需将A[i]
返回作为第i
小的元素即可。其他情况,就会调用第4行的randomized_partition(arr,low,high)
,将数组
A
[
p
⋯
r
]
A[p\cdots r]
A[p⋯r]划分为两个(可能为空的)子数组
A
[
p
⋯
q
−
1
]
A[p\cdots q-1]
A[p⋯q−1]和
A
[
q
+
1
⋯
r
]
A[q+1\cdots r]
A[q+1⋯r],使得
A
[
p
⋯
q
−
1
]
A[p\cdots q-1]
A[p⋯q−1]中的每个元素都小于或等于
A
[
q
]
A[q]
A[q],而
A
[
q
]
A[q]
A[q]小于或等于
A
[
q
+
1
⋯
r
]
A[q+1\cdots r]
A[q+1⋯r]中的每个元素。与快速排序中一样,我们称
A
[
q
]
A[q]
A[q]为主元。
randomized_select(arr, low, high, i)
的第5行计算子数组
A
[
p
⋯
q
]
A[p\cdots q]
A[p⋯q]内的元素个数
k
k
k,即处于划分的低区的元素的个数加1,这个1指主元。然后,第6行检查
A
[
q
]
A[q]
A[q]是否是第i小的元素。如果是,第7行就返回
A
[
q
]
A[q]
A[q]。否则,算法要确定第
i
i
i小的元素落在两个子数组
A
[
p
⋯
q
−
1
]
A[p\cdots q-1]
A[p⋯q−1]和
A
[
q
+
1
⋯
r
]
A[q+1\cdots r]
A[q+1⋯r]的哪一个之中并递归地查找。
randomized_select(arr, low, high, i)
的最坏情况运行时间为
∣
T
h
e
t
a
(
n
2
)
|Theta(n^2)
∣Theta(n2),即使是找最小元素也是如此,因为在每次划分时可能极不走运地总是按余下的元素中最大的来进行划分,而划分操作需要
∣
T
h
e
t
a
(
n
)
|Theta(n)
∣Theta(n)时间。但是,我们也可以简单地证明该算法有线性的期望运行时间,又因为它是随机化的,所以不存在一个特定的会导致其最坏情况发生的输入数据。