快速选择算法——求解第k小的数

1.问题描述

给定n个无序的数,求出其中第k小的数

2.问题分析

求一个无需数列中第k小的数最简单的方法就是先使用快速排序或是选择排序对数组排序,然后直接挑选升序序列中的第k个数作为结果。此时算法的时间复杂度为O(nlogn)。

3.快速选择

快速选择是一种利用了快速排序的性质从而在平均时间复杂度O(n)的情况下选择出无序数组中第k小的元素的算法。在快速排序中我们首先会从数组中选择一个数作为划分标准,将比该数小的放在左边,比该数大的放在右边,经过一轮划分后实际上我们已经确定了这个被选择的数在排序后的数组中的正确位置p。如果我们此时将p和k作比较,会发现当p和k相同时,此时数组第p位的数就是我们要找的第k小的数。如果p>k则在左边的划分中寻找第k小的数,反之在右边的划分寻找第k-p小的数。通过观察我们可以发现,每次我们只需要选择一个子集合进行划分, T ( n ) = T ( n 2 ) + O ( n ) T(n)=T(\frac{n}{2})+O(n) T(n)=T(2n)+O(n)

4.算法模板

int findKth(int a[], int l ,int r,int k){
    
    
    if (l == r) return a[l];
    
    int x = a[l + r >> 1] , i = l - 1 , j = r + 1;
    while (i < j){
    
    
        while (a[++i] < x);
        while (a[--j] > x);
        if (i < j) swap(a[i] , a[j]);
    }
    //计算主元左边数字个数
    int lcnt = j - l + 1;
    //判断第k个数在左边还是右边
    if (k <= lcnt) return findKth(a, l, j, k);
    else return findKth(a, j + 1, r, k - lcnt);
}

猜你喜欢

转载自blog.csdn.net/qq_33880925/article/details/128840945