判断是否存在重复的数【青少年等级考试一级】

2022-02-19 23:29:27           39     

题目描述

在一个长度为n的数组里的所有数都在0到n-1的范围内。
 数组中某些数是重复的,但不知道有几个数是重复的,也不知道每个数重复几次。
请找出数组中第一个重复的数。

输入

第一行一个整数n,表示n个整数1<=n<=10000

第二行n个数,范围在0到n-1之间

输出

输出第一个重复的数。

样例输入 

7
2 3 1 0 2 5 3

样例输出 

2


这个题对于初学者来说,如果n是一个最比较小的数,解决的方法很多。这里我们来介绍两种比较容易想的解决方法。


方法一:

用一个数组a来保存输入的数据,当每次读入一个整数后,先和数组中原来的元素依次比较,如果有相同的直接输出即可。

因为所有数据是是0到n-1的范围,所以我们要先将数据每个元素值设置为-1,确保数据默认值和输入的值都不相同,这里用下面的函数实现。

 memset(a,-1,sizeof(a));

下面以样例数据为例,介绍实现过程:

数组a开始没有存读入的数,所以每个值都是-1。

一共需要输入7个数,需要循环7次,我们用 i 作为循环变量,i=0开始,同时用 i 表示之前读入数据的个数。

第1次输入2,此时i=0,检查数组a中是否有2,此时数组a中没有存数据,设置a[0]=2;

第2次输入3,此时i=1,检查前面输入的数据a[0]是否等于3,发现不等于3,设置a[1]=3;

第3次输入1,此时i=2,检查前面输入的数据a[0]、a[1]是否等于1,发现都不等于1,设置a[2]=1;

第4次输入0,此时i=3,检查前面输入的数据a[0]、a[1]、a[2]是否等于0,发现都不等于0,设置a[3]=0;

第5次输入2,此时i=4,检查前面输入的数据a[0]、a[1]、a[2]、a[3]是否等于2,发现a[0]等于2,找到了重复的数,直接输出,结束程序即完成任务。

代码实现如下:

#include<iostream>
using namespace std;
int n,a[10000],k;
int main() {
    memset(a,-1,sizeof(a));
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>k;
		for(int j=0;j<i;j++)
		{
			if(a[j]==k) {
				cout<<k<<endl;
				return 0;
			}
		}
		a[i]=k;
	}
	return 0;
}

这种解决方法容易想到,但我们看下时间复杂度,

按最差的情况来计算。就是执行 1+2+3+4+...+n-1=(n-1)x(1+n-1)/2=(n2-n)/2,可以是O(n2)的时间复杂度,当n比较大(比如n=1000000)时,可能会超时。




方法二:

用桶排序(也叫箱排序)的方法,这里我们桶的数量直接设置成n的大小,这样每个数一个桶,当n比较大(比如n=1000000)时,也可以正常解决。

这里就能再详细介绍过程了,具体可以参见桶排序。

#include<iostream>
using namespace std;
int n,k;
bool a[1000000];
int main() {
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>k;
		if(a[k]>0) {//对应值大于0说明出现重复,结束
			cout<<k;break;
		}
		else a[k]=1;
	}
	return 0;
}

我们看到,这里最多循环n次,时间复杂度为O(n),比方法一的效率大大提高。

TAGpjax代码无刷新

标签云更多