您的位置:首页 > 编程语言 > C语言/C++

【C++】找数组中唯一出现两次的数

2017-05-09 10:51 253 查看
题:假设你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?

方法一、使用辅助的存储方式,该选择何种存储方式呢?可使用hash的存储方式,以1到1000作为hash表的索引,遍历原数组,统计各数字出现的个数并存储到以该数字为索引值的hash表中,若某个hash[x]的值为2则退出循环,x就是重复出现两次的数字。时间复杂度最坏是O(n)。优点:高效率,缺点:消耗的内存空间过大。

代码如下所示:

int hash[7]={0};
for(int i=0;i<7;++i){
if(++hash[a[i]]==2){
cout<<"result:"<<a[i];
break;
}
}


这个方法是本人认为解这里问题的比较好的一种方法,对于问题的变形也具有一定的鲁棒性。比如题目改变成:在一个数组中有1000个数字,数字范围是1到1000,其中只有一个是重复的剩下的都不重复。


方法二,采用异或的方式来求取

思想:1001个数异或结果与1-1000异或的结果再做异或,得出的值即位所求。

原理:

设重复数为A,其余999个数异或结果为B。1001个数异或结果为A^A^B。1-1000异或结果为A^B。由于异或满足交换律和结合律,

则有 (A^B)^(A^A^B)=A^B^B=A

代码如下:

int a[7]={1,4,5,6,2,3,5};
int i=0,j=0;
int b[6]={1,4,6,2,3,5};
int temp=a[0];
for(i=1;i<7;++i){
temp=temp^a[i];
}
int temp2=b[0];
for(j=1;j<6;++j){
temp2=temp2^a[j];
}
int result = temp^temp2;
cout<<"result:"<<result;


用异或的方法解决此类问题可扩展性也非常好,比如,当题目变形为:在一个数组中只有一个数是不重复的剩余的数都出现了两次,现在求不重复的那个数。

思路:异或中两个相同的数相异或结果为0,0与其他数异或都是其他数。代码如下:

int a[5]={5,4,5,1,4};
int i=0,j=0;
int temp=a[0];
for(i=1;i<5;++i){
temp=temp^a[i];
}
cout<<"result:"<<temp;



方法三,求和法

这个是完全的数学思想的一种方法:想将原数组S1的所有元素的加起来,然后再将S2={1,2,...,1000}折1000个数的所有元素加起来,最后做减法就能得到出现仅两次的那个数了。

但是这个方法的局限性很强,比如将题目变形一下:在一个数组中有1000个数字,数字范围是1到1000,其中只有一个是重复的剩下的都不重复(也就是在这1000个数据中有一个数出现了两次,有一个数一次都没出现),若是求那个重复的数字是多少?此时用这个方法就行不通了。此时使用方法一能够解决。

若是求那个没出现的数字是多少,就需要方法一和方法三合作求出了。先用方法一求出重复的数字x,然后sum(s2)-(sum(s1)-x);其中s1是输入的数组,s2是1到1000的数组。

这个题目只是这类题目中的一个,变形的有很多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数组 唯一值
相关文章推荐