这个题目本身就有一定局限性。比如,对于数组a[10001],其中,1000个数就是1~1000的每个数,可以任意排列,然后再多一个重复的数。题目就是怎么求出这个特殊的重复的数。
这一类问题的解决思路主要有以下几种:
方法一:先求和,再相减。即数组元素值求和,然后数组下标求和,然后二者相减,即可得到重复的数。
void xor_findDup1(int *a,int len)
{
int sum1=0;
int sum2=0;
for(int i=0;i<len;i++)
{
sum2+=a[i];
}
for (int i=0;i<len;i++)
{
sum1+=i;
}
int num=sum2-sum1;
cout<<"唯一重复的数为:"<<num<<endl;
}
方法二:异或法。a^a^b=b;a^a=0;a^b=1;0^b=b。该方法可先将数组元素异或,然后将下标异或,最后将两个异或结果异或,比如:a[1,2,3,4,2],下标为:[0,1,2,3,4]。异或最终只剩下0^2=2.
void xor_findDup2(int *a,int len)
{
int i;
int result =0;
for(i=0;i<len;i++)
{
result ^=a[i]; //数组元素异或,保存结果到result
}
for (i=0;i<len;i++)
{
result^=i; //result结果和数组下标序号异或,最终结果依然保存在result中
}
printf("重复数字为:%d\n",result);
}
方法三:位图法。即用一个位去记录数据的存放方式。不过,若数组长度为N,则需要N位。
这种方法的思路是,设立一个长度为N的标志数组,并初始化为false。然后遍历数组,每遍历一个数,在对应的i位置处记录该数标志位true,若已经是true了,说明这个数是重复的数。
void xor_findDup3(int *a,int len)
{
int *arrFlag= (int *)malloc(len*sizeof(int));
int i=1;
while(i<len)
{
arrFlag[i] =false;
i++;
}
for (i=0;i<len;i++)
{
if (arrFlag[a[i]] ==false )
arrFlag[a[i]] =true;
else
printf("重复数字为:%d\n",a[i]);
}
}
扩展 不是一个重复数字,而是多个重复数字的情况。
依然可以使用位图法,把重复的数字都输出即可。