网课:[NOIP2006]明明的随机数——牛客(题解)

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N ≤ 100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

输入描述:

输入有2行,第1行为1个正整数,表示所生成的随机数的个数:N
第2行有N个用空格隔开的正整数,为所产生的随机数。

输出描述:

输出2行,第1行为1个正整数M,表示不相同的随机数的个数。
第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

示例1

输入

复制10 20 40 32 67 40 20 89 300 400 15

10
20 40 32 67 40 20 89 300 400 15

输出

复制8 15 20 32 40 67 89 300 400

8
15 20 32 40 67 89 300 400

解法1:

对数列进行去重(输入一个就和前面输入的比较,相同就标记一下),再排列。我觉得它的去重挺巧妙的吧,读入元素顺便完成,和前面的元素比。我的话就直接把整个数组都读了,再去重,去重也不一定要删除,直接标记一下就好了,删掉太麻烦了。时间复杂度O(n^2)

代码:

#include
using namespace std;
int a[110];
int main(){
    int n;
    cin>>n;
    int cnt=0;
    for(int i=0;i         cin>>a[i];
        for(int j=0;j             if(a[i]==a[j]){
                a[i]=-1;
                break;
            }
        }
        if(a[i]!=-1) cnt++;
    }
    sort(a,a+n);
    cout<     for(int i=0;i         if(a[i]==-1) continue;
        cout<         if(i!=n-1) cout<<' ';
    }
}

解法2:

先排列,再去重。也是超级巧妙,去重那里,不用删,不用标记,直接相同的就不输出,不相同的就输出,达到去重的目的。时间复杂度O(n*log n)

代码:

#include
using namespace std;
int a[110];
int main(){
    int n;
    cin>>n;
    for(int i=0;i         cin>>a[i];
    sort(a,a+n);
    int cnt=0;
    for(int i=0;i         if(i==0) cnt++;
        else if(a[i]==a[i-1]) continue;
        else cnt++;
    }
    cout<     for(int i=0;i         if(i==0) cout<         else if(a[i]==a[i-1]) continue;
        else cout<         if(i!=n-1) cout<<' ';
    }
}

解法3:

用桶排序(我一直以为这东西是哈希表来着……)达到去重和排序的作用。时间复杂度O(n)

代码:

#include
using namespace std;
int a[1010];
int main(){
    memset(a,0,sizeof(a));
    int b,n;
    cin>>n;
    for(int i=0;i         cin>>b;
        a[b]++;
    }
    int cnt=0;
    for(int i=0;i<1000;i++){
        if(a[i]) cnt++;
    }
    cout<     for(int i=0;i<1000;i++){
        if(a[i]){
            cout<             cnt--;
            if(cnt) cout<<' ';
        } 
    }
}

总结:

去重的四种方法:输入时去重(标记一下),输出时去重(有相同不输出),利用”桶“去重,直接删除

你可能感兴趣的:(算法)