算法 求最小值,最大值,中位数,顺序统计量
分别求最小值,最大值的比较次数是N
同时求最小值最大值的比较次数是1.5N
中位数和顺序统计量
中位数就是按大小排序,位置在元素个数中间的那个
顺序统计量是按大小排序,第i个元素
利用分治法求中位数或顺序统计量的方法是
int randomized_select(int *a,int l,int r,int i)
{
if(l==r)return a[l];
int index=randomized_partition(a,l,r);// 利用partition算法算出某个值在排好序的最终索引
int k=index-l+1;// 得到索引对应的位置
if(k==i)
return a[index];
else if(i>index)
{
return randomized_select(a,index+1,r,i-k);// 注意i-k,在高位区求第i个要减去低位区的个数了
}
else
{
return randomized_select(a,l,index-1,i);
}
}
在元素互异的情况下,平均时间O(N)内可以得到答案
最坏情况下则O(N^2),类似快速排序
算法导论中
最坏情况为线性时间O(N)的选择算法(查找第i个顺序统计量被视为选择算法)
SELECT算法
1.将数组划分为每5个一组的元素列,保证只有最后一级不足5个
2.每组进行插入排序,得到每组的中位数 // 这里被认为在O(1)的集合中使用了O(N)的时间
3.对2得到的中位数列递归调用SELECT算法得到中位数值x // 求中位数的中位数
4.利用 partition算法划分原数组,得到k,即x在原数组的最终位置
5.如果i=k,返回x,如果小于或大于,递归SELECT
分析:
时间复杂度为O(N)的分析具体见算法导论,
这里只分析与上面的随机化SELECT在最坏情况下的差别,
随机化SELECT每次递归得到的范围是不固定的,如果每次随机PARTITION的值总是在一边的端点处,则最后退化为简单交换类排序(冒泡排序);
SELECT算法则先利用分治求中位数的办法O(N),得到中位数,再利用PRTITION,固定地求中位数在排序后的最终位置,使每次递归都平均地在N/2的范围内求解