快速选择算法

对于一个无序的序列,找出其中第k大的数,你会怎么做呢?一个容易想到的做法是,先将原序列按降序排序,再输出第k个元素。这种做法是正确的,只不过在数据范围较大时不太适用,主要是因为排序算法一般选择快排之类的,复杂度是O(nlogn)。那么有没有更优秀的方法呢?是有的,而且思想和快排相似。不妨回忆一下快排的过程,我们在完成一趟排序后,又递归地处理左右子序列,现在我们只是要找第k大的数,那么在确定基准元素的位置后,就可以确定第k大元素所处的位置是在左子序列还是右子序列,或者第k大元素就是基准元素。这样最多只需要去递归处理一个子序列,平均复杂度近似为O(n),不过最坏情况下还是O(n^2)。

 1 void move_mid(int l,int r) {
 2     int m=l+(r-l)/2;
 3     if(a[l]>a[m]) swap(a[l],a[m]);
 4     if(a[m]>a[r]) swap(a[m],a[r]);
 5     if(a[l]<a[m]) swap(a[l],a[m]);
 6 }
 7 int getKth(int l,int r) {
 8     if(l==r) return a[l]; //当区间长度为1,说明该元素就是第k大元素
 9     move_mid(l,r); //三数取中法,简单地优化
10     int x=a[l],i=l,j=r;
11     while(i<j) {
12         while(a[j]<=x&&i<j) --j;
13         a[i]=a[j];
14         while(a[i]>=x&&i<j) ++i;
15         a[j]=a[i];
16     }
17     a[i]=x; //快排过程
18     if(i>k) return getKth(l,i-1); //通过与基准元素位置
19     if(i<k) return getKth(i+1,r); //确定第k大元素的位置
20     return x; //若均不满足,则基准元素就是第k大元素
21 }

 

转载于:https://www.cnblogs.com/Mr94Kevin/p/9497953.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值