选择问题:选出无序数组中的第k小的数(以排序顺序)

问题描述

  • 输入:A =[A0,A1,…,A_{n-1}],k < n
  • 输出:第 k 小的数(特例:中位数)

基本思路

  • 将数组排序,然后访问第 k 个就是第 k 小
  • 复杂度主要是排序,最好也需要 O(nlogn)
  • 我们只需要找第 k 小,并不需要完全排序的一个结构,是否可以用一点排序的操作,就能找出来呢?

优化方法

  • Divide and Conquer 的方法
  • 快速排序的代码框架几乎一样,只不过不需要完全排序,是一个不断递归寻找的过程,一旦寻找到,则完成
  • 时间复杂度最好为 O(n),最差为 O(n^2),平均 O(n),这个复杂度和每次选取的pivot的值相关,所以也出现很多选择 pivot 的算法,尽量选择接近中心的pivot。
    • BFPRT 算法。median of three
    • QuickSelect 算法,随机选取 pivot
    • Floyd-Rivest 算法

代码实现

#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int par(vector<int>& v, int l, int r){
    int i = l, j= l;
    int pivot = v[r];
    while(i<r && j<r){
        if(v[j] <= pivot){
            swap(v[i],v[j]);
            i++;
            j++;
        }else{
            j++;
        }
    }
    swap(v[i],v[r]);
    return i;
}
int QuickSelectKth(vector<int>&v, int l, int r, int k){
    if(k>r-l+1 || k<1){
        cout<<"Invalid search range!";
        return 0;
    }
    int p = par(v,l,r);//这里的par函数只能用L的,因为得到的v[p]左边都是比它小的,右边都是比它大的,H的则不可以,只是基于pivot分为两半,v[p]不一定是pivot
    int kth = p-l+1;//这个是S-数组的大小,不能直接用p,因为p是原数组的下标,不是第几小
    if(kth == k)
        return v[p];
    else if(kth > k)
        return QuickSelectKth(v,l,p-1,k);
    else
        return QuickSelectKth(v,p+1,r,k-kth);
}
int main(){
   vector<int>v{2,5,7,10,11,4,3,6,8,1,9};
   int k = 3;
   int res = QuickSelectKth(v,0,v.size()-1,k);
   cout<<res;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值