找出不同数字

找出不同数字

  一个整型数组里除了一个或者两个或者三个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

1,如果只有一个出现一次,考察到异或的性质,就是如果同一个数字和自己异或的活结果为零,那么循环遍历一遍数组,将数组中的元素全部做异或运算,那么出现两次的数字全部异或掉了,得到的结果就是只出现一次的那个数字。

2,如果有两个只出现一次的数字,设定为a,b。也是应用异或,但是数组元素全部异或的结果x=a^b,因为a,b是不相同的数字,因此x肯定不为0。对于x,从低位到高位开始,找到第一个bit位为1的位置设定为第m位,这个第m位的bit肯定来自a或者来自b,不可能同时a,b的第m位(从低到高位)都为1。这样,就可以根据这个第m位就可以把数组分为两个部分,一组为第m位为0,一组为第m位为1.这样,就把问题分解成了求两个数组中只出现一次的数字了。下面首先给这部分的程序和实例分析:
 
 1 int get_first_position(int num)  
 2 {//从低位开始找到第一个位1的bit位  
 3     int index=1;  
 4     int i=0;  
 5     while(i<32)  
 6     {  
 7         if((num&(1<<i))==(1<<i))  
 8             break;  
 9         else  
10         {  
11             index++;  
12             i++;  
13         }  
14     }  
15     return index;  
16 }  
17 int is_bit_one(int num,int index)  
18 {//判断给定的索引位置的bit位是否为1  
19     num=(num>>index);  
20     return num&1;  
21 }  
22 void get_two_unique_num(int *a,int n,int *num1,int *num2)  
23 {  
24     int exclusive_or_result=0;  
25     *num1=0;  
26     *num2=0;  
27     for(int i=0;i<n;i++)  
28         exclusive_or_result^=a[i];  
29     int index=get_first_position(exclusive_or_result);  
30     for(i=0;i<n;i++)  
31         if(is_bit_one(a[i],index))  
32             (*num1)^=a[i];  
33     for(i=0;i<n;i++)  
34         if(!is_bit_one(a[i],index))  
35             (*num2)^=a[i];  
36 }  
37 void main()  
38 {  
39     int a[]={2,2,4,4,6,6,3,5};  
40     int num1,num2;  
41     get_two_unique_num(a,sizeof(a)/sizeof(int),&num1,&num2);  
42     printf("%d	%d
",num1,num2);  
43 }

参考:http://blog.csdn.net/zzran/article/details/8108787

  

原文地址:https://www.cnblogs.com/tekkaman/p/3713118.html