题目
一个int数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。
思路
由于3个数字出现一次,其他数字均出现两次,因此可以得到n一定为奇数。
3个只出现一次的数字,他们的bit位肯定不可能全部相同,也就是说,虽然有些bit位上的数可能相等,但肯定至少存在某一个bit位,这三个数中,有两个数的该bit位为1,一个数的该bit位为0,或者两个数的该bit位为0,一个数的该bit位为1。
我们可以通过扫面int的所有bit位,扫描每个bit位的时候,遍历数组,如果能找出符合上面条件的,我们就可以找出其中的一个只出现一次的数字,该数字与另外两个只出现一次的数的bit位不同。找到一个之后,就可以将其与数组的最后一个元素交换,再在前面n-1个数中找出另外两个就可以了,方法的话,可以直接用上篇博文中介绍的方法,也可以用该博文介绍的思路。
下面要来看下如果找出这个与另外两个数的该bit位不同的数。
先看第一种情况,如果a,b,c三个数中,有两个该bit位为0,另一个为1,我们遍历数组,分别统计该数组元素中该bit位为1和0的元素个数,分别设为count1和count0,并同时将所有该bit位为1的元素异或,所有该bit位为0的元素异或,得到的结果分别设为temp1和temp0。如果count1为奇数,则可能有两种情况,a,b,c三个数的该bit位全为1,或者有两个为0,一个为1,如果有temp0==0,则说明是前一种情况(a,b,c的该bit位全为1的话,所有该bit位为0的每个元素出现了两次,因此异或后的结果为0),即3个只出现一次的数均在第1类中,此时没法找出其中的一个数,则直接跳到下次循环,继续判断下一个bit位,如果temp0不等于0,则说明是后一种情况(说明该比bit位为0的元素异或后没有完全抵消,则说明在此类中有两个数字只出现一次),此时其中一个只出现一次的数字就在另一类中,值就是temp1(重复的元素异或后都抵消了)。
同理:第二种情况也是类似的,如果 count0为奇数时,且temp1!=0时,则说明有两个值出现了一次的数在bit=1的这类中,另一个则在bit=0的那一类中,且值为temp0;
将上面的思路在图上显示如下:
编码实现如下:
/*
一个int数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。
*/
/*
思路:按照上面提供的思路,现在3个次数值出现一次的数字中找出其中一个,然后利用上篇博文中找出两个在数组只出现一次的数字的方法。
*/
#include<stdio.h>
#include<stdlib.h>
int xorArr(