线性时间选择
要求:
给定线性序集中n个元素和一个整数k,1<=k<=n,要求找出n个元素中第k小的元素。
方法一 随机选择法
算法的思路如下:
从a[p:r]中随机选择一个元素将其划分为三部分
1.a[p:q-1],其中元素都小于等于a[q]
2.a[q],我们设定的划分基准
3.a[q+1:r],其中的元素都大于等于a[q]
a[p:q]的元素个数为m=q-p+1(例如就有两个元素,其下标为p和p+1,元素个数2=(p+1)-p+1)
拿我们要找的数字序号k跟m比较:
如果k =m,那么我们很幸运地找到了,它就是a[q]。
如果k>m,这说明标号为k的元素在大于a[q]的部分,也就是在a[q+1,r]中,我么要找的元素的编号在这一部分数组内就变为k-m。
如果k<m,这说明标号为k的元素在小于a[q]的部分,也就是在a[p,q-1]中,编号仍为k。
我们递归上述过程就能最终找到要找的元素。
在最坏的情况下,算法需要O(n^2),其平均时间复杂度为O(n)
方法二 改进最坏情况下的复杂度
我们要求在最坏的情况下,算法的时间复杂度也要达到O(n)
如果能够在线性时间内找到一个划分基准,使得按照这个基准所划分出的2个子数组的长度都至少为原数组的x倍(x∈(0,1)),那么就可以在最坏的情况下用O(n)时间完成任务。
步骤:
1.将n个输入的元素划分为n/5个组,每个组5个元素,最后一个组可以不足5个。
2.利用任意一种排序算法对所有组进行排序,取出每个组的中位数。
3.找出所有组中位数的中位数,并以此为依据进行数组的划分。
为什么要这么做呢?
因为以中位数的中位数为划分时,比这个数字大和比这个数字小的元素都至少为3*(n-5)/10个,原因是:
3*(n/5-1)*1/2
3---中位数比x小的每一组中有3个元素比x小
n/5-1---有5个数的组数
1/2---大概有1/2组的中位数比x小
而当n>=75时,3(n-5)/10≥n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4,也就是说,长度最长为原长度的3/4。
4.划分完成后对其递归上述过程就能得到结果。