1.问题描述
设计算法实现在一个具有在n各互不相同元素的数组A[1…n]中找出所有前k个最小元素的问题,这里k不是常量,即它是输入数据的一部分。要求算法的时间复杂性为Θ(n)。
2. 具体要求
输入的第一行是一个正整数m,表示测试例个数。接下来几行是m个测试例的数据,每个测试例的数据由三行组成,其中其中,第一行输入一个正整数n,表示元素的个数;第二行输入n个整数,整数之间用一个空格隔开。第三行输入一个正整数k,表示求该组测试例中的前k个最小元素。(设给出的每个整数序列中的元素是唯一的。)
输出:对于每个测试例输出一行,由k个整数组成,表示输入的n个整数中前k个最小元素。整数之间用一个空格隔开。两个测试例的输出数据之间用一个空行隔开。
说明:限于Acm平台,要求输出数据按从小到大排序。算法的时间复杂性也相应地放宽要求。
3. 测试数据
输入:
2
19
56 34 22 7 16 95 46 37 81 12 73 26 19 31 68 42 3 72 51
8
26
8 33 28 17 51 57 49 35 11 25 37 14 3 2 13 52 12 6 2 32 54 5 16 22 23 7
13
算法 SELECT1
输入:n各互不相同元素的数组A[1…n]
输出:前k小元素
select(A,1,n,k);
output A[1..k];
end SELECT1
过程 select(A,low,high,k)
//求A[low..high]中的第k小元素并返回。
p=high-low+1 //p为当前处理的元素个数。
if p<44 then // 当元素个数<44时,直接求解。
将A[low..high]排序
return(A[low+k-1])
end if
// 以下分解子问题。
q= ;//将A[low..high]每5个分组,剩余的被排除。
将A[low..low+5q-1]分为q组, 每组5个元素;
将q组中的每一组单独排序并找出中项,所有的中项存于数组M[1..q]中;
mm=select(M , 1, q, ) //求中项序列M的中项mm
找到mm在A[low..high]中的下标 i
互换A[low]和A[i]
w=split(A,low,high);
case:
w>k select(A,low,w-1,k);
w=k return;
w<k select(A,w+1,high,k-w);
end case
end select
过程: SPLIF
输入:n个元素的数组A[1…n],和number
输出:以number为中值将A之分开
过程:select_k
输入:n个元素的数组A[1…n]
输出:数列中的第1~k小元素
Select_k(A,1,n,k)
Num <- select(A,low,high,k)
A[k]=A[1];
A[1]=num;
quicksort(A,1,n);
return A[1…k];
endSelect_k