题目的主要信息:

  • 一共多次调查,每次调查输入的第一个数为N,后续N个数随机(1-1000)的数字
  • 需要对每次调查数字排序并去重后输出,每个数字一行

方法一:暴力排序去重

具体做法:

我们每次循环优先读取下面的数组长度,即优先读取N,然后用循环连续N个数字进入数字,这就是这次调查的全部数字了,然后我们使用sort函数快排对这些数字排序,排好序后我们就可以输出了,需要注意除了第一个元素外我们都要检查是否和前一个元素相等,相等我们就不输出,这样来去重。

alt

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main(){
    int n;
    while(cin >> n){ //首先输入每次调查的人数n
        vector<int> v(n);
        for(int i = 0 ; i < n; i++) //连续输入n个整数
            cin >> v[i];
        sort(v.begin(), v.end()); //排序
        for(int i = 0; i < n; i++){ //去重输出
            if(i != 0 && v[i] == v[i - 1])
                continue;
            else
                cout << v[i] << endl;
        }
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(nlog2n)O(nlog_2n)O(nlog2n)nnn为输入的总数字个数,输入输出都是一次遍历,而排序是分段排序,最坏情况下才是O(nlog2n)O(nlog_2n)O(nlog2n)
  • 空间复杂度:O(n)O(n)O(n)nnn为输入的总数字个数,中途记录数据的数组最坏情况下长度为n1n-1n1

方法二:有序集合

具体做法:

读取数据的方式和方法一一致,但是我们这里不采用数组来记录数字,而是采用set。set作为集合它可以对添加的数据自动去重,而且依赖于红黑树的它内部是有序,我们也省去了排序的操作,最后直接遍历set,输出即可。需要注意,每次要清空set中的内容,避免上次调查的数据用到了这次。

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;

int main(){
    int n;
    set<int> s;
    while(cin >> n){ //首先输入每次调查的人数n
        s.clear(); //每次调查清空集合
        for(int i = 0 ; i < n; i++){
            int temp;
            cin >> temp;  //连续输入n个整数
            s.insert(temp);  //插入集合中,自动排序去重
        }
        for(auto iter = s.begin(); iter != s.end(); iter++) //遍历集合直接输出即可
            cout << *iter << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(nlog2n)O(nlog_2n)O(nlog2n)nnn为输入的总数字个数,set依赖于红黑树,每次插入都是O(log2n)O(log_2n)O(log2n),最坏情况下只有一个数组,需要O(nlog2n)O(nlog_2n)O(nlog2n)
  • 空间复杂度:O(n)O(n)O(n)nnn为输入的总数字个数,最坏情况下set大小为n1n-1n1