如何求出一个或两个不是成对存在的数

关于按位异或运算符 ^

运算规则:参与^运算两个二进制位不同时,结果为 1,相同时结果为 0。
例:2^5  ===> 0010 ^1001 ===> 1011

特别的:
0^5 =5 0000^1001 ===>1001
15^10=5 1111^1010 ====> 0101
总结 :

  1. 按位异或运算可以用来将某些二进制位反转
    将需要反转的对应位异或二进制的1,则实现反转
  2. 0跟任何一个整数异或值不变

案例一: 数组中所有数都是成对出现,只有一个数只出现一次,找出这个数

  • 分析:根据异或规则,相同的数异或为0,0跟任何一个整数异或 值不变
  • C程序实现:
#include <stdio.h>
int one_array(int*,int);

int main()
{
	int a[] = {2,4,6,5,4,2,6};
	int len = sizeof(a)/sizeof(a[0]);
    int num = one_array(a,len);
	printf ("num = %d\n", num);
	return 0;
}

int one_array(int a[],int len)
{
    int i;
    int num=0;
    for(i=0;i<len;i++)
    {
        num^=a[i];
    }
    return num;
}

案例二: 数组中所有数都是成对出现,有两个数只出现一次,找出这个两个数

  • 分析:我们还利用案例一的解决方法,但是有两个不同数,将数组元素全部异或并不能得出两个数,那么我们选择把这两个数分开,分成两个数组,怎么分开呢?根据什么条件能把他们分开呢?
    首先,我们来看两个不同的数的异或:
    1^3 ===> 0001^0011 = 0010
    从二进制的角度来看,1不同于3,就是有对应的位是不同的
    从异或结果上来看,不同的位异或结果为1
    那么好,我们有条件了,可以根据异或结果 第一个为1的位数来分组。还是1和3,我们可以根据他们二进制第二位是0还是1把他们分开,1二进制第二位是0,3二进制第二位是1。
  • C程序实现:
#include <stdio.h>
int main()
{
    int a[]={1,5,2,5,4,1};
    int len=sizeof(a)/sizeof(a[0]);
    int num =0;
    int num1=0;
    int num2=0;
    //第一步:将数组元素全部异或,得出两个不同的数异或结果
    int i;
    for(i=0;i<len;i++)
    {
        num^=a[i];
    }
    //第二步:找出异或结果二进制的第一个1的位数
    int count=1;
    while(0==num&1)
    {
        num>>=1;
        count++;
    }
    //第三步:分组异或
    for(i=0;i<len;i++)
    {
        if((a[i]>>count)&1)
        {
            num1^=a[i];
        }
        else
        {
            num2^=a[i];
        }
    }
    printf("num1=%d  num2=%d\n",num1,num2);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40144572/article/details/84318390
今日推荐