异或运算

异或运算法则

  • 如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以 异或常被认作不进位加法。(来源于搜狗百科)

例如,计算 1011101^1000011:
在这里插入图片描述

异或性质与扩展

(用不进位相加较好理解)

  • 0 ^ N = N
  • N ^ N = 0
  • 异或运算满足交换律和结合律
    c =a ^ b =b ^ a
    c =( a ^ b )^ c = a ^ ( b ^ c )
  • 不用额外变量交换两个数: 在这里插入图片描述
  • 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到这个数?
    例如,该数组为 a[]={1, 2, 2, 3, 3}
    将所有的数全部异或运算,运算结果就是出现了奇数次的数。
  • 一个数组中有两种出现了奇数次,其他数都出现了偶数次,怎么找到这两个数?
    例如,该数组为a[]={1,2,4,4,5,5}
    1. 让该数组中所有的数字做异或运算,那么设结果 eor == a ^ b != 0 ;
    2. 因为eor 不为 0 ,则可以假设 a 与 b在某位上,比如在第三位上,a第三位是1,则b的第三位为0;
    3. 在其余的出现偶数次的数字中,找出所有在第三位为1的数;
    4. 用变量 eor’ 与这个数组中所有第三位为1的数做异或运算 ,则 eor’ 最终的答案为a,因为所有第三位为1的数字,除了a,其余为偶数个,异或运算后为0。(因为除了a 与 b ,其余数字的个数都为偶数个,那么可以确定第三位为1的和第三位为0的个数都为偶数个。因为 eor = a ^ b,且其余偶数运算之后结果为0,如果第三位为1的数字个数为奇数,那么第三位为0的数字个数也为奇数,那么将他们全部进行异或运算后,第三位数字为1,不为0,与实际不符。)
    5. 再用eor与eor’做异或运算,即a ^ b ^ a = b, 再计算 eor ^ eor’ ^ eor ,即 b ^ a ^ b = a;

以下给出该题解的代码:首先了解如何取到该数最右端的1,就是该数取反加一再与该数 (核心:int rightOne = eor & ( ~ eor + 1 );
在这里插入图片描述

 public static void printOddTimesNum(int[] arr){
   int eor=0;
   for(int i=0;i<arr.length;i++)
    eor^=arr[i];
   //提取出最右端的1
   int rightOne=eor&(~eor+1);
   
   int onlyOne=0; //eor' 
   //找出这个数组中所有在最右端为1的数字,做异或运算
   for(int cur:arr){
    if((cur&rightOne)!=0)
    //说明该数当前位上的数字也是1
    {
        onlyOne^=cur;
    }
   }
   System.out.println(onlyOne+" "+(eor^onlyOne));
 }
  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值