【问题描述】设无序序列 T =(r1, r2, …, rn),T 的第k(1≤k≤n)小元素定义为T按升序排列后在第k个位置上的元
素。给定一个序列T和一个整数k,寻找 T 的第k小元素的问题
称为选择问题。
当k=1时,相当于找最小值。
当k=n时,相当于找最大值。
当k=n/2时,相当于找中值(中位数)。
#include <iostream>
using namespace std;
int QuickSelect(int a[],int left,int right,int k)
{
if(left>right)
return -1;
int i,j,t,temp;
temp=a[left];
i=left;
j=right;
while(i!=j)
//理解为i与j相碰时的空就是temp所在位置
{
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left]=a[i];
a[i]=temp;
if(i==k-1) return a[i];
else if(i<k-1) return QuickSelect(a,i+1,right,k);
else return QuickSelect(a,left,i-1,k);
}
int main()
{
int a[10]={1,3,2,5,9,7,3,6,10,8};
int k;
cin>>k;
cout<<QuickSelect(a,0,9,k)<<endl;
return 0;
}
时间复杂度分析:
最好情况:每次划分的轴值恰好是序列的中值,则可以保证处理的区间比上一次减半,由于在一次划分(O(n))后,只需处理一个子序列
最坏情况:每次划分的轴值恰好是序列中的最大值或最小值,则处理区间只能比上一次减少1个,所以:
T(n) = T(n-1) + O(n) =O(n2)
平均情况:假设每次划分的轴值是划分序列中的一个随机位置的元素,则处理区间按照一种随机的方式减少,可以证明,算法的平均时间是O(n) 。