题目地址:
https://www.luogu.com.cn/problem/P1138
题目描述:
现有
n
n
n个正整数,要求出这
n
n
n个正整数中的第
k
k
k个最小整数(相同大小的整数只计算一次)。
输入格式:
第一行为
n
n
n和
k
k
k;第二行开始为
n
n
n个正整数的值,整数间用空格隔开。
输出格式:
第
k
k
k个最小整数的值;若无解,则输出NO RESULT
。
数据范围:
n
≤
10000
n \leq 10000
n≤10000,
k
≤
1000
k \leq 1000
k≤1000,正整数均小于
30000
30000
30000。
先用哈希表相同数字只保留一个,接着用快速选择算法。代码如下:
#include <iostream>
#include <unordered_set>
using namespace std;
const int N = 1e4 + 10;
int n, k, a[N], idx;
unordered_set<int> st;
int quick_select(int l, int r) {
if (l >= r) return a[l];
int i = l, j = r, piv = a[l + (r - l >> 1)];
while (i <= j) {
while (a[i] < piv) i++;
while (a[j] > piv) j--;
if (i <= j) {
swap(a[i], a[j]);
i++;
j--;
}
}
if (k <= j) return quick_select(l, j);
else if (k >= i) return quick_select(i, r);
else return a[k];
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
if (!st.count(x)) {
st.insert(x);
a[++idx] = x;
}
}
if (k < 1 || k > idx) puts("NO RESULT");
else printf("%d\n", quick_select(1, idx));
}
时空复杂度 O ( n ) O(n) O(n)。