快速排序->快速选择算法

早就听说快排改造能实现O(n)求第k小数,不过做到的题目基本上都可以快排/大根堆所以没研究过……

上周一位前辈提到淘宝的试题,貌似是在10W个不同数里面选出来最小的10个?渣渣第一反应就是快排T_T前辈说可以维护一个长度为10的链表,每次和其中最大的那个数比较替换就行,而且是O(n),我整个人就Orz了……
但是前辈也说如果挑出来最小的1W个就没办法了,只能用快排。我觉得维护一个尺寸为1W的大根堆稍快,然后又想到传说中的快速选择,如果选出来第1W小的数,循环输出所有小于等于它的就可以而且貌似还是O(n)?

正好回老家就YY了一个(这还用YY?)……
大体思路么,首先快排求k小是肯定没问题的;其次快排递归完的区间就能保证区间内数字在正确的位置上;再次我们只找一个数的排名,而这个数要么在[l,j]要么在[i,r]要么在(j,i),在(j,i)之间不进行递归显然已经排好了,不然直接递归一边就行。又考虑到既然只进行一边就是个很简单的尾递归了所以改成循环,然后就没有然后了……

粘代码……

int a[10000],n;
int qcho(int k) {
  for (int l=1,r=n,i,j,x; l<r; k>=i?l=i:r=j) {  
    i=l,j=r,x=a[l+r>>1];
    do {
      while (a[i]<x) i++; while (a[j]>x) j--;
      if (i<=j) {int y=a[i]; a[i++]=a[j]; a[j--]=y;}
    } while (i<=j);
    if (j<k&&k<i) return a[k];
  }
  return a[k];
}

 

不对啊,说好的10W怎么变成1W数组了?额,不要在意细节……

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值