数组中只出现一次的数字

题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路:先看一个简单的实例,若是找数组中只出现一次的一个数,其它的数都出现两次,直接对数组元素进行位异或就可以得到数组中只出现一次的一个数。本题中,找数组中只出现一次的两个数,则要将数组分成2个子数组,每个子数组中仅存在出现一次的一个数。关键就在于分组的标准,而对数组中所有的元素进行异或,得到的是这个数的异或。这个结果不为0,则一定存在某一个数字的一位为1,另一个数字中的某位为0,这样异或的结果才不为0。因此分组的标准是对数组元素全部进行异或的结果中首位为1的那一位(假设是第N位)。然后以这个数与数组中元素进行与运算,进行分组。数组元素第N位为1的分一组,为0为另一组。在每个子数组中进行全部异或,最终可以得出数组中只出现一次的两个数。

 1 #include "stdafx.h"
 2 
 3 unsigned int FindFirstBitIs1(int num);
 4 bool IsBit1(int num, unsigned int indexBit);
 5 
 6 void FindNumsAppearOnce(int data[], int length, int* num1, int* num2)
 7 {
 8     if(data == NULL || length < 2)
 9         return;
10     
11     int resultExclusiveOR = 0;
12     for(int i = 0; i < length ; ++ i)
13         resultExclusiveOR ^= data[i];
14     
15     unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
16     
17     *num1 = *num2 = 0;
18     for(int j = 0; j < length ; ++j)
19     {
20         if(IsBit1(data[j], indexOf1))
21             *num1 ^= data[j];
22         else
23             *num2 ^= data[j];
24     }
25 }
26 
27 // 找到num从右边数起第一个是1的位
28 unsigned int FindFirstBitIs1(int num)
29 {
30     int indexBit = 0;
31     while(  ((num & 1) == 0)  && (indexBit < 8*sizeof(int))   )
32     {
33         num = num >>1;
34         ++ indexBit;
35     }
36     
37     return indexBit;
38 }
39 
40 // 判断数字num的第indexBit位是不是1
41 bool IsBit1(int num, unsigned int indexBit)
42 {
43     num = num >> indexBit;
44     return(num & 1);
45 }
46 
47 int main()
48 {
49     int data[] = {2, 4, 3, 6, 3, 2, 5, 5};
50     int length = sizeof(data) / sizeof(int);
51     
52     int result1, result2;
53     FindNumsAppearOnce(data, length, &result1, &result2);
54     
55     printf("%d  %d
", result1, result2);
56     
57     return 0;
58 }

原文地址:https://www.cnblogs.com/sankexin/p/5635970.html