算法导论9-2
读书笔记
本小节介绍一种选择算法,用来选择数组中第\(i\)小的元素;
\(RANDOMIZED-SELECT\)以快速排序为模型,时间复杂度为\(\theta(n)\)。
伪代码如下:
RANDOMIZED-SELECT(A, p, r, i)
if p == r
return A[p]
q = RANDOMIZED-PARTITION(A, p, r)
k = q - p + 1
if i == k
return A[q]
else if i < k
return RANDOMIZED-SELECT(A, p, q - 1, i)
else return RANDOMIZED-SELECT(A, q + 1, r, i - k)
关于\(RANDOMIZED-PARTITION\)请查阅第七章快速排序的内容,这个函数的作用是根据随机数对给定范围的数组分区,比随机数大的在右边,比随机数小的在左边。
对伪代码的解读:
- 如果指定范围内的数组只有一个元素,则返回这一元素。
- 然后通过\(RANDOMIZED-PARTITION\),获取随机数在数组中的次序。
- 对比这一次序,符合则返回这一元素。
- 然后根据次序和\(i\)的比较,递归执行左枝或者右枝;
对时间复杂度的分析过程看的头疼,略。
课后习题
9.2-1
证明:在\(RANDOMIZED-SELECT\)中对长度为\(0\)的数组,不会进行递归调用。
答案显而易见,空集不会调用函数。
9.2-2
请讨论:指示随机变量\(X_k\)和\(T(max(k-1,n-k))\)是独立的。
略。
9.2-3
给出\(RANDOMIZED-SELECT\)的一个基于循环的版本。
public int randomnized_select_loop(int[] a, int start, int end, int i) throws Exception{
if(i > a.length || i <= 0)
throw new Exception("Invalid i!");
if(a.length == 1)
return a[0];
int mid = qs.partition_Randomized(a, start, end);
while(mid + 1 != i){
if(mid + 1 < i) //search right
mid = qs.partition_Randomized(a, mid + 1, end);
else //search left
mid = qs.partition_Randomized(a, start, mid - 1);
}
return a[mid];
}
9.2-4
假设用\(RANDOMIZED-SELECT\)去选择数组\(A=<3,2, 9, 0, 7,5,4,8,6,1>\)的最小元素,给出能够导致\(RANDOM-SELECT\)最坏情况发生的一个划分序列。
也就是快速排序中最不平衡的情况,\(<0,1,2,3,4,5,6,7,8,9>\)。