啦啦啦。。。。。。。
首先我们先找出:数组中只有一个数字出现一次,其余数字都成对出现。实现的方法其时间复杂度为O(1);
使用异或:其数字的二进制位相同为0,不同为1.所有数字都异或,最后的异或结果就是那个只出现一次的数字。
下面是代码实现:
void FindDifference(int arr[],int n) { int i = 0; int s = arr[0]; if(n == 0 || n == 1) { return; } for(i = 1;i < n;i++) { s = s^arr[i]; } if(s == 0) { printf("数组中所有的数字都是成对出现。\n"); } else { printf("单独的数字是:%d\n",s); } }
如果数组中有两个数字出现一次,那么。。。。。。。
我们只需要把一个数组分成两个数组,然后一个数组中有一个没有成对出现的数字,让其逐一进行异或,就可以找出只出现一次的数字。下面我们举个例子来促进理解:int[] = {1,2,3,4,1,2};
整个数组异或的结果为:3(0x011)^4(0x100)=7(0x111)(若异或结果的某一位为1,就说明那两个数字的那位是不同的);对于0x111,(从低位到高位)第一位就是1.所以就可以根据整个数组的第一位是1还是0来进行分组:
arr[0] 0x001; 第一组
arr[1] 0x010; 第二组
arr[2] 0x011; 第一组
arr[3] 0x100; 第二组
arr[4] 0x001; 第一组
arr[5] 0x010; 第二组
然后第一组和第二组分别进行异或,就可以找出不同的两个数字了。
下面是具体的代码实现:
void FindTwoNumbers(int *arr,int n) { int i = 0; int j = 0; int tmp = 0; int n1 = 0,n2 = 0; for(j = 0;j < n;j++) { printf("%d ",arr[j]); } printf("\n"); for(i = 0;i < n;i++) { tmp ^= arr[i]; } for(i = 1;i <= 32;i++) { if((tmp >> i) & 1 == 1) { break; } } for(j = 0;j < n;j++) { if(((arr[j] >> i) & 1) == 0) { n1 ^= arr[j]; //在分组的同时进行异或。 } else { n2 ^= arr[j]; } } printf("只出现一次不同的两个数字是:%d,%d",n1,n2); }
以上都是在VS2008的环境下运行的结果。