一个整形数组里除了两个数字以外,其他数字都出现了两次,找出这两个只出现一次的数字。
用异或运算来解题,首先看一下异或的特点:
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 }
结果: