例如1,2,3,4,5,1,2,3,4这一组数,5出现次数为一次,编写程序找出出现次数为1的数。
1.暴力遍历
用一个变量保存1,将数组往后遍历,如果出现了1则跳出;用一个遍历保存2,重复上面的步骤,直到程序不跳出,出现次数为一的数就找了出来。
2.异或每个数
两个相同的数异或结果是0,0与任何数异或结果还是原来的数。将数组中的每个数异或。0与数组中第一个数异或,其结果再与数组中第二个数异或…如此重复,两个相等的数异或运算后结果为0,只有出现次数为1的数,没有数与它异或使两数结果为0。所以最后的结果就是出现次数为1的数
找出出现次数为1次的两个数
一个数组:1,2,3,4,5,6,1,2,3,4。5和6出现次数为一次,找出这两个数。按照异或的思想,得到的结果使5与6异或的结果。结果首先不可能是0,那么用二进制表示结果,其中肯定有一个1,只需要从结果的最低位开始向最高位遍历,找到1出现的位置,用pos记录。
而数组是由,二进制序列中pos位置为1与为0的数组成。将数组分成两组,分别在两组中有出现次数1次的数。所以现在问题简化成了在数组中找出出现次数1次的数,用异或的算法就能得到结果。
int main()
{
int arr[10] = { 1,2,3,4,5,6,3,4,5,6 };
int i = 0;
int ret = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
ret ^= arr[i];
for (i = 0; i < 32; i++)
{
if ((ret & (1<<i)) == 1)
break;
else
i++;
}
int pos = i;
int single1 = 0;
int single2 = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if ((arr[i] & (1 << pos)) == 0)
single1 ^= arr[i];
else
single2 ^= arr[i];
}
printf("%d %d", single1, single2);
return 0;
}