Description
开学了,ACM队的边老板想在学校中请一些妹子一起做一项问卷调查,调查妹子们对ACM的了解情况,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的妹子的编号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。老板怎么会自己去解决这么简单的问题了,所以就请你协助完成“去重”与“排序”的工作啦。
Input
第一行是一个正整数 T ,表示这一组测试数据的总个数。
每一组的第一行包含一个数N
每一组的第2行有N个用空格隔开的正整数,为所产生的随机数。
Output
对于每一组数据,输出为2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
Sample Input
2 10 20 40 32 67 40 20 89 300 400 15 3 1 2 3
Sample Output
8 15 20 32 40 67 89 300 400 3 1 2 3
这个题目描述就是一个不重复的计数排序,但是正因为如此,可以直接使用set容器。可重复的可以使用map容器。
计数排序很好理解,s[i]存的就是数字i的个数。不过需要初始化全为0。这样来一个i,s[i]就自加。
然后输出所有非0的s[i]的i,用flag控制一下空格输出。
这个算法的复杂度是O(max(n, p)),其中p为整个数列里的最大值,这里p <= 1000, n <= 100
但是使用set容器的话,只用把所有的数加入容器,然后顺序输出即可,复杂度是O(nlogn)
由于这里n比p小了一个数量级,所以第二种方法更快一点,事实证明第一种跑了2MS, 第二种跑了1MS。
代码:
计数排序版:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <set> using namespace std; int s[1005], n, cnt, len; void Input() { int v; memset(s, 0, sizeof(s)); cnt = len = 0; scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", &v); if (!s[v]) cnt++; s[v]++; len = max(len, v); } } void Output() { bool flag = false; printf("%d ", cnt); for (int i = 1; i <= len; ++i) { if (!s[i]) continue; if (flag) printf(" "); printf("%d", i); flag = true; } printf(" "); } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 0; times < T; ++times) { Input(); Output(); } }
set容器版:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <set> using namespace std; void Input(set <int> &s) { int n, v; scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", &v); s.insert(v); } } void Output(set <int> &s) { bool flag = false; printf("%d ", s.size()); set <int> :: iterator it; for (it = s.begin(); it != s.end(); ++it) { if (flag) printf(" "); printf("%d", *it); flag = true; } printf(" "); } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 0; times < T; ++times) { set <int> s; Input(s); Output(s); } }