题目大意
给定数列,求第 $k$ 小的数。
分析
模板题。考虑分治,随便选一个数 $x$,然后把比 $x$ 大的数移到右边,比 $x$ 小的数移到左边。因此得到了数 $x$ 的排位,若恰为第 $k$ 个则返回,否则根据大小在左右寻找。
该算法是不稳定的,期望复杂度 $O(n)$,最坏复杂度 $O(n^2)$。
实际上存在最坏复杂度为 $O(n)$ 的 BFPTR 算法,但因为其常数过大实现复杂而很少应用。
ll nn[5000010], k, n;
ll quicksort(ll l, ll r) {
ll i = l, j = r;
ll x = nn[(l + r) / 2];
while (i <= j) {
while (nn[j] > x)
j--;
while (nn[i] < x)
i++;
if (i <= j) {
swap(nn[i], nn[j]);
i++, j--;
}
} // l <= j <= i <=r
if (k <= j)
return quicksort(l, j);
else if (k >= i)
return quicksort(i, r);
else
return nn[k + 1];
}
int main() {
n = rr(), k = rr();
for (ll i = 1; i <= n; i++)
scanf("%lld", &nn[i]);
printf("%lld", quicksort(1, n));
return 0;
}