不重复数字

题目描述:

小李最近遇到了一个难题,聪明的你帮她解决一下吧。

 

给出N个数,要求把其中重复的去掉,只保留第一次出现的数。

 

例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。

 


 

输入:

 

输入第一行为正整数T,表示有T组数据。

 

接下来每组数据包括两行,第一行为正整数N,表示有N个数。第二行为要去重的N个正整数。

 

输出:

对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。

 


 

样例输入:

2

11

1 2 18 3 3 19 2 3 6 5 4

6

1 2 3 4 5 6 

样例输出:

1 2 18 3 19 6 5 4

1 2 3 4 5 6

 


 

分析

对于这道题,我们可以这么想:我们首先把这些数据全部存进一个数组里,然后把这个数组的第一个元素拿出来,假设赋给a,再用一个循环,把这个元素依次与它后面的元素作比较,一旦发现有相同元素,假设把这个相同元素赋给b,然后我们再弄一个循环,让b后面的元素依次往前面移一位,这样就完成了去重。当然这整个过程都在一个循环里面完成。代码实现如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 100
 4 int a[N];
 5 int main(void)
 6 {
 7     int n,t;
 8     int i,j,m,x;
 9     int T;
10     scanf("%d",&T);
11     while(T--)
12     {
13         scanf("%d",&n);
14         for(i=0;i<n;i++)
15         { 
16             scanf("%d",&a[i]);
17         }
18         
19         m = n;
20         for(i = 0;i < m;i++)
21         { 
22             x = a[i];
23             n = m;
24             for(j = i + 1;j < n;j++)
25             { 
26                 if(a[j] == x)
27                 { 
28                     for(int k = j;k < n-1;k++)
29                     { 
30                         a[k] = a[k+1];
31                     }
32                     n--;
33                 }
34             }
35             m = n;
36         }
37         
38         for(i = 0;i < m;i++)
39         {
40             printf("%d ",a[i]);
41         }
42         
43         n = 0;
44         printf("\n");
45     }
46     return 0;
47 }

来看下运行效果:

 

 这样子就挺好的。

但是,如果仔细思考这个程序的算法思想,就会发现一个问题,那就是,这个程序里面,先不说输入的循环,光是完成这个去重操作的部分,就有三重循环了,这样一来,它的时间复杂度直接就到了O(n³).数据不多还好,万一去重的数据很多,毫无疑问,这种算法的效率是很低的。因此,我们可以考虑另外一种算法:

我们可以声明两个数组,其中一个用来存放要去重的数据,假设这个数组为a,另外一个数组用来存放去重后的数据,假设为b。我们可以在遍历未去重的数组时,先把第一个数据放进b数组里,然后在遍历a时,每碰到一个数据,我就先判断一下,看是否已经存在于b数组里了,如果已经存在,不管继续看下一个;如果不存在的话,就放进b数组。来看看代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 50000
 4 int a[N],b[N];
 5 int main(void)
 6 {
 7     int n,t,count;
 8     int i,j,m,x,k;
 9     int T;
10     scanf("%d",&T);
11     while(T--)
12     {
13         scanf("%d",&n);
14         for(i=0;i<n;i++)
15         { 
16             scanf("%d",&a[i]);
17         }
18 
19         count = 1; 
20         b[0] = a[0];  //先把第一个数据存在b数组里 
21         for(i = 1;i < n;i++)  //便利a数组 
22         { 
23             x = a[i];  //把第i个值取出来,便于以后依次与b数组里的数据比较 
24             for(k = 0;;k++)  //便利已存了数据的b数组,看是否有相同数字 
25             {        
26                 if(x == b[k]) break;  //只要有相等的马上跳出循环 
27                 
28                 if(k == count - 1)  //如果把整个b数组遍历完了都没有相同数字 
29                 {
30                     b[count++] = x;  //就先把x赋给b数组,然后count再加加 
31                     break;  //这一步是为了无论如何都要跳出循环,因为k不可能一直自增下去 
32                 }
33             }
34         }
35         
36         for(k = 0;k < count;k++)
37         {
38             printf("%d ",b[k]);
39         }
40         printf("\n");
41         
42     }
43     return 0;
44 }

(说明:以上代码中的count就是去重后数组的最终长度。)

这样一来,不考虑输入部分的循环,这种算法的时间复杂度就是O(n²).可以极大地提高效率。来看看运行效果:

 

 

posted @ 2021-01-31 16:39  EvanTheBoy  阅读(180)  评论(0)    收藏  举报