题目描述
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
输入格式
输入有2行,第1行为1个正整数,表示所生成的随机数的个数:
N
第2行有N个用空格隔开的正整数,为所产生的随机数。
输出格式
输出也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
解答:同样用顺序存储结构即数组,排序上一题已经做过,所以本题的重点为如何去重复,基于我现在掌握的知识,我想到的办法为:先将数组排序,然后寻找某元素之前有无与该元素相同的元素,如果有则将相同元素删去,删除用到的方法就是被删除元素之后所有的元素向前进位。
具体代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <malloc.h> 4 #define MAXSIZE 100 5 6 typedef int status; 7 typedef struct{ 8 int key; 9 }Redtype; 10 11 typedef struct{ 12 Redtype r[MAXSIZE]; 13 int length; 14 }*SqList, LNode; 15 16 void SelectSort(SqList L){ 17 Redtype temp; 18 int i; 19 for (i = 0; i < L->length; i++){ 20 int l=i; 21 int j; 22 for (j = i + 1; j < L->length; j++){ 23 if (L->r[j].key < L->r[l].key) 24 l = j; 25 } 26 if (i != l){ 27 temp = L->r[i]; 28 L->r[i] = L->r[l]; 29 L->r[l] = temp; 30 } 31 } 32 } 33 34 int LocateRepeat(SqList L, int j){ 35 int i = 1; 36 while (i < j){ 37 if (L->r[i - 1].key != L->r[j - 1].key) 38 i++; 39 else 40 break; 41 } 42 if (i < j){ 43 return i; 44 } 45 else{ 46 return 0; 47 } 48 } 49 50 int main(int argc,char *argv[]){ 51 SqList L; 52 L = (LNode*)malloc(sizeof (LNode)); 53 scanf("%d", &L->length); 54 if (L->length > MAXSIZE) 55 exit(0); 56 int i; 57 for (i= 0; i < L->length; i++){ 58 scanf("%d", &L->r[i].key); 59 if (L->r[i].key<1 || L->r[i].key>1000) 60 break; 61 } 62 SelectSort(L); 63 int m = 2; 64 while(m <= L->length){ 65 int j = LocateRepeat(L, m); 66 if (j != 0){ 67 for (j; j < L->length; j++){ 68 L->r[j - 1] = L->r[j]; 69 } 70 --L->length; 71 } 72 else 73 m++; 74 } 75 printf("%d ", L->length); 76 int n; 77 for (n = 0; n < L->length; n++){ 78 printf("%d ", L->r[n].key); 79 } 80 return 0; 81 }
由本题得到的领悟:
1、RQNOJ不支持C99,即如果用C语言提交,不能出现C99的标准。对于今天来讲,for的格式,C和C99就有区别:对于C99,可以这样定义:
for(int i=0;i<n;i++);
而对于C,只能如下定义,
int i;
for(i=0;i<n;i++)
所以注意区分。
2、去重复出现的几个问题:
a、无法定位重复元素所在位置,原因是没有考虑查找到相同元素之后如何处理,导致i一直自增;解决方法:for循环改为while循环,当找到相同元素则用break跳出循环,即可定位重复元素。
b、只能去除一个重复元素,原因是main函数里,无论有无找到重复元素都m会加一,删除了重复元素之后,原来数组元素的位置都向前进了一位,此时m加一,就无法删除另外的重复元素。所以解决办法是只在找不到重复元素时再加一,这样就可以保证所有的重复元素都可以剔除。
3、RQNOJ的运行平台为Linux,所以对C语言main函数的定义有所区别,即int main(int argc,char *argv[])多加两个参数即可。