一个整形数组里除了两个数字以外,其他数字都出现了两次,找出这两个只出现一次的数字。

用异或运算来解题,首先看一下异或的特点:

1.0^0=0,0^1=1,1^0=1,1^1=0,即相同取0,不同取1,那么相同的两个整数异或结果为0,任何整数与0异或都等于其本身

2.异或满足交换律,即a^b^c=a^c^b

所以,将数组中的数从头到尾依次异或,出现偶数次的数异或都为0,最终结果是两个只出现一次的数字异或的结果,由于这两个数字不同,异或的结果一定不为0,即其二进制表示形式中一定存在某一位为1,找到第一个为1的位,假设是第N位,那么在对应的这一位上,这两个数一个为0,一个为1,根据第N位是否为1,将原数组分成两个子数组,这两个子数组分中都只包含一个只出现了一次的数,其他的数都出现了两次,两个子数组中的元素分别异或,就得到了两个只出现一次的数。

 

 1 #include<iostream>
 2 using namespace std;
 3 bool IsBit1(int num,unsigned int indexBit)   //判断num的第indexBit位是否为1,位数从0算起
 4 {
 5     num=num>>indexBit;   //将num的第indexBit移到末尾
 6     return(num&1);     //1除了第一位,其余为均为0,&操作结果必为0,决定结果的只是第indexBit位
 7 }
 8 
 9 unsigned int FindFirstBitIs1(int num)
10 {
11     int indexBit=0;
12     while(num>0&&(num&1)==0)
13     {
14         indexBit++;
15         num=num>>1;
16     }
17     return indexBit;
18 }
19 
20 void FindNumsAppearOnce(int data[],int length,int &num1,int &num2)
21 {
22     if(length<2) return;
23     int result=0;
24     for(int i=0;i<length;i++)
25         result=result^data[i];
26     int indexBit=FindFirstBitIs1(result);
27     num1=num2=0;
28     for(int i=0;i<length;i++)
29     {
30         if(IsBit1(data[i],indexBit))   //根据第indexBit是否为1将数组分成两组,并进行异或
31             num1=num1^data[i];
32         else
33             num2=num2^data[i];
34     }
35 
36 }
37 void main()
38 {
39     int a[10]={1,1,2,2,3,3,4,4,5,6};
40     int num1,num2;
41      FindNumsAppearOnce(a,10,num1,num2);
42      cout<<num1<<" "<<num2;
43 
44 }

结果:

 

posted on 2016-04-28 14:47  小菜鸡y  阅读(1827)  评论(0编辑  收藏  举报