随机选择算法-选择第K大

2019-03-16  本文已影响0人  crishawy

问题描述

从一个无序数组中求出第K大的数,如{5,12,7,2,9,3},第三大的数是5,第五大的数是9.
一种思路直接先排序,取出第K个元素即可,但时间复杂度最少也是O(nlogn),而使用快速排序的思想,时间复杂度可以降低为O(n)

思路

当对A[left,right]执行一次randPartiton之后,主元左侧的个数是确定的且都小于主元,右侧的元素均大于主元,不妨令主元是A[p],此时A[p]是A[left,right]中第p-left+1大的数

程序代码

int randPatition(int A[],int left,int right)
{

    //生成[left,right]的随机数
    int p =  round((1.0*rand()/RAND_MAX)* (right - left) + left);
    swap(A[left],A[p]);
    int temp = A[left];
    //只要left与right不相遇
    while(left <right)
    {
        //右边
        while(left < right && A[right] > temp) right --;
        A[left] = A[right];
        //左边
        while(left < right && A[left] <= temp) left ++ ;
        A[right] = A[left];
    }
    //left与right相遇的地方放置temp
    A[left] = temp;
    //返回相遇的下标
    return left;
}

void randSelect(int A[],int left,int right,int k)
{ //划分序列,形成以A[p]为主元第k大的数,使其左边小于它,右边大于它
    //随机选择划分,那么A[p]是该序列中第p-left+1大的

    if(left == right) //边界
        return ;
    int p = randPatition(A,left,right);
    int M = p - left + 1;
    if(k == M)
        return;
    else if(k < M) randSelect(A,left,p-1,k);
    else randSelect(A,p+1,right,k-M); //这里注意寻找第K-M大!
}
上一篇 下一篇

猜你喜欢

热点阅读