一题多解(五) —— topK(数组中第 k 大/小的数)

根据对称性,第 k 大和第 k 小,在实现上,是一致的,我们就以第 k 小为例,进行说明:

法 1

直接排序(sort(A, A+N)),当使用一般时间复杂度的排序算法时,其时间复杂度为 O(N2)

法 2

先将 k 个元素读入一个数组并将其排序,sort(A, A+k),则这些元素的最大值在第 k 个位置上。我们一个一个处理剩余的元素,当一个元素开始被处理时,它先于数组中第 k 个元素比较,

  • 如果该元素大,不做任何处理,遍历下一个元素;
  • 如果该元素小,则将该元素插入在前面合适的位置;

代码逻辑可参考 插入排序(insertion sort)

此时的时间复杂度为:O(k2+(Nk)k)=O(Nk)

法 3:借助数据结构

优先队列,DeleteMin 执行 k-1 次,

法 4:借助快排的 partition 函数

根据 partition 函数返回值与 k 的关系,然后继续进行 partition:

int partition(int*A, int N, int s, int e) {
    if (!A || N <= 0 || s < 0 || e >= N)
        throw exception("");
    int toSwap = s - 1;
                            // 以最后一个元素作为 pivot,然后进行
    for (int i = s; i < e; ++i) {
        if (A[i] < A[e]) {
            ++toSwap;
            if (toSwap != i) {
                swap(A[toSwap], A[i]);
            }
        }
    }
    ++toSwap;
    swap(A[toSwap], A[e]);
}

int topK (int*A, int N, int k) {
    int p = partition(A, N, 0, N-1);
    while (p != k-1) {
        p < k-1 ? p = partition(A, N, p+1, N-1) : p = partition(A, N, 0, p-1);
    }
    return A[p];
}
原文地址:https://www.cnblogs.com/mtcnn/p/9423550.html