当前位置: 首页>>算法&结构>>正文


线性时间复杂度求数组中第K大的数【原创】

丹阳 算法&结构, 算法的力量 , 去评论

求数组中第K大的数可以基于快排序思想,步骤如下:

1.随机选择一个支点

2.将比支点大的数,放到数组左边;将比支点小的数放到数组右边;将支点放到中间(属于左部分)

3.设左部分的长度为L,

当K < L时,递归地在左部分找第K大的数

当K > L时,递归地在有部分中找第(K - L)大的数

当K = L时,返回左右两部分的分割点(即原来的支点),就是要求的第K大的数

以上思想的代码实现如下:

0368a22e762979741f3089e2

 

 

#include <iostream>
using namespace std;

int selectk(int a[], int low, int high, int k)
{
    if(k <= 0) return -1;
    if(k > high - low + 1) return -1;
    int pivot = low + rand()%(high - low + 1);
    swap(a[low], a[pivot]);
    int m = low;
    int count = 1;

    //一趟遍历,把较大的数放到数组的左边

    for(int i = low + 1; i <= high; ++i)
    {
       if(a[i] > a[low])
       {
            swap(a[++m], a[i]);
            count++;
       }
    }
    swap(a[m], a[low]);
    if(count > k)
    {
        return selectk(a, low, m - 1, k);
    }
    else if( count < k)
    {
       return selectk(a, m + 1, high, k - count);
    }
    else
    {
       return m;
    }
}
int main(int argc, char** argv)
{
    /*1,1,1,1,1,1,1,1,3,5,5,7,9,10,10,12,15,16,17,18,19,100,1000*/
    int a[] = {5, 15, 5, 7, 9, 17,100, 3, 12, 10, 19, 18, 16, 10, 1000,1,1,1,1,1,1,1,1};
    int r = selectk(a, 0, sizeof(a) /sizeof(int) - 1, 5);
    cout<<(r == -1 ? r : a[r])<<endl;
    system("pause");
    return 0;
}
本文由《纯净的天空》出品。文章地址: https://vimsky.com/article/379.html,未经允许,请勿转载。