一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。请找出这两个数
例如:1 2 3 4 5 6 1 2 3 4 -> 5 6
预备知识:
(1)两个相同的数异或的结果是0;
(2)所有不为0的数和0异或的结果是本身。
有了以上的了解,可以将数组的元素分成两组,按照这样的原则:
- 要找的两个数分到不同的组
- 相同的数要分到同一个组内
比如:1 1 2 2 3 3 6, 4 4 5
分成这样的两个组之后,每个组的元素异或的结果便是要找的两个元素。
那么,如何进行分组呢?下面为具体步骤:
为了方便理解,写出1-6的二进制序列:
| 1 -> 001 | 2 -> 010 |
| 3 -> 011 | 4 -> 100 |
| 5 -> 101 | 6 -> 110 |
- void Find(int arr[], int sz, int *px, int* py)
- {
- int i = 0;int ret = 0;int pos; int num1,num2;
- //1. 要把所有数字异或
- for (i = 0; i < sz; i++){
- ret ^= arr[i];
- }
- //2. 计算ret的哪一位为1
- pos = 0;
- for (i = 0; i < 32; i++){
- if (((ret >> i) & 1) == 1){
- pos = i;
- break;}
- }
- //3. 把从低位向高的第pos位为1的数放在一个组,为0的放在另外一个组。
- num1 = 0; num2 = 0;
- for (i = 0; i < sz; i++){
- if (((arr[i] >> pos) & 1) == 1)
- num1 ^= arr[i];
- else
- num2 ^= arr[i];
- }
- *px = num1;*py = num2;
- }
-
- int main()
- {
- int arr[] = { 1,2,3,4,5,6,1,2,3,4 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- int x = 0, y = 0;//输出型参数
-
- Find(arr, sz, &x, &y);
- printf("%d %d\n", x, y);
- return 0;
- }