一组数组中只有一个数(两个数)出现一次,其他的都成对出现,找出该数

一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。请找出这个数字。(使用位运算)
     >可以这么理解:如果两个数相等,它们异或之后的结果是0。而0与任何数异或都是该数本身。
   (比如00000001^00000001结果是0。00000000^00000001=00000001)  
    那么将一组数中所有元素异或,相同的数字结果是0,最后的结果就是单独出现的数字。 
编程实现如下:
#include <stdio.h>
#include <windows.h>
int main()
{
    int arr[]={1,2,3,4,5,1,2,3,4};
    int i=0;
    int j=0;
    for(i=1;i<sizeof(arr)/sizeof(arr[0]);i++)
    {
    arr[0]=arr[0]^arr[i];  //将它们整体异或
}
printf("the single is:%d
",arr[0]);
system("pause");
return 0;
 }

那如果是一组数据中有两个数字出现了一次。其他所有数字都是成对出现的。该如何找出这两个数字。(使用位运算)

     这个问题用常规的方法也可以做,依次遍历数组,查找不相同的数,打印出来。
但接着用上面的方法该怎么做呢,首先我们先分析一下:和上面的一样将整个数组异或一遍,得到一个结果,该值可以看成是要查找的两个数异或得来的。
比如一组数1,2,3,1
  1:     00000001
  1:     00000001
  2:     00000010
  3:     00000011
  异或:00000001
整体 异或值肯定不等于1,那么找比特位不为0的位,该位处相同的数据,比特位是一样的;该位处不同的数据比特位是不一样的,现在分两个组分别存放这两部分,即相同的数据划分到一组,不同的数据划分到不同组。不用考虑每组中存放多少个元素,反正相同的数据肯定放在一个组中。然后问题就转化为第一题的样式,即每个分组中有一个数出现了一次,其他数都是成对出现。
代码实现如下:
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void find_diff_data(int arr[],int len)
{
    assert(arr);
    assert(len>2);
    int i = 0;
    int value = arr[0];
    for(i = 0;i < len;i++)
    {
        value ^= arr[i];  //整体异或
    }
    int farg = 1;
    i = 0;
    while(i < 32)
    {
        if(value & (farg <<= i))  // 查找为1的比特位
        {
            break;
        }
    i++;
    }
    i = 0;
    int data1 = 0;
    int data2 = 0;
    for(i = 0;i < len;i++)
    {
        if(arr[i] & farg)
        {
            data1 ^= arr[i];  
        }
        else
        {
            data2 ^= arr[i];
        }
    }
    printf("%d  %d",data1,data2);
}
int main()
{
    int arr[] = {1,2,3,4,5,6,1,2,3,4};
    int len = sizeof(arr)/sizeof(arr[0]);
    find_diff_data(arr,len);
    system("pause");
    return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/xjq6898/p/7819745.html