根据对称性,第 k 大和第 k 小,在实现上,是一致的,我们就以第 k 小为例,进行说明:
法 1
直接排序(sort(A, A+N)
),当使用一般时间复杂度的排序算法时,其时间复杂度为
法 2
先将 sort(A, A+k)
,则这些元素的最大值在第 k 个位置上。我们一个一个处理剩余的元素,当一个元素开始被处理时,它先于数组中第 k 个元素比较,
- 如果该元素大,不做任何处理,遍历下一个元素;
- 如果该元素小,则将该元素插入在前面合适的位置;
代码逻辑可参考 插入排序(insertion sort)
此时的时间复杂度为:
法 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];
}