一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。请找出这个数字。(使用位运算)
>可以这么理解:如果两个数相等,它们异或之后的结果是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; }