深入理解异或操作

异或操作与数据结构。

1.异或操作介绍

一、异或操作符号

c = a^b.  

二 、异或操作定义

abc = a^b
000
101
011
110

三、异或性质的延伸

  • 0 ^ N = N 零与任意数异或仍为其自身
  • N ^ N = 0 任意值相同的数异或结果恒为零
  • A ^ B ^ C = B ^ A ^ C 即异或满足交换律
  • (A ^ B)^ C = A ^ (B ^ C) 即异或满足结合律

如何理解异或操作的交换律与结合律?或者说为什么异或操作满足结合律与交换律?

如果单单从数的按位异或层面,确实很难理解。但异或操作还有一个性质,便是异或操作等价于无进位的加法操作。读者可以自行演算,即每一位相加,产生的进位位不对高位传递。

那么,从无进位的加法层面,交换律与结合律变很好理解了,即由于加法操作的交互律与结合律,加之不产生进位。很容易推出异或操作的结合律与交换律。

异或数据交换算法

根据以上性质,对于任意具有独立存储空间的数,有如下算法可以在不需要第三个变量的情况下,完成 数组中两数的交换(注意,两数不能为同一存储单元,否则会直接将其清零)

void swap (int * arr ,  int i, int j){
     arr[i]  =  arr[i]  ^  arr[j];
     arr[j]  =  arr[i]  ^  arr[j];
     arr[i]  =  arr[i]  ^  arr[j];
}

让我们举个例子来更形象的理解上述过程:

  1. 令 a = 甲 ; b = 乙;
  2. a = 甲 ^ 乙 ; b = 乙;
  3. b = ( 甲 ^ 乙) ^乙 = 甲 ^ (乙 ^乙)=甲
  4. a = ( 甲 ^ 乙) ^甲=(甲 ^ 甲) ^乙 = 乙

根据以上1~3步,便完成了在不使用新内存的情况下,数据ab的交换。

数据结构处理案例

  1. 假设有 N 个数,其中 只有一种数出现了奇数次,其余种数均出现了偶数次。
    /
    问: 在算法时间复杂度O(n)与空间复杂度O(1) 的约束下,如何找出N个数中出现奇次个数的数?

答:

int  findNum(int *arr, int n){
     int eor  = 0;
     for(int i=0;i<n;i++){
          eor  ^=  arr[i];
      }
      return eor;
}

2.同样假设有N个数,其中 有两种数出现了奇数次,其余种的数均出现了偶数次。
问: 在算法时间复杂度O(n)与空间复杂度O(1) 的约束下,如何找出N个数中出现奇次个数的数?

void findNum(int *arr , int n ){
      int eor1 = 0, eor2 = 0;
      for(int i=0;i<n;i++){
            eor1  ^=  arr[i];
      }
      int rightOne = eor1 & (~eor1 + 1) ; //提取出最右侧的“1”
      for(i = 0;i<n; i++){
           if( (arr[i]&rightOne) == 0 ){  //当该数中与提取出“1”的位为 0 时,则选取;
                eor2 ^= arr[i];
           }
       }
       eor1 = eor1^eor2;
       printf("The Numbers are %d and %d",eor1,eor2);
       return;
}

这里简单讲解一下第二问的思路。首先按照第一问的思路,将数组中所有数异或之后,应得到的eor1 = a ^ b(假设所求两数为a 、b)。那么,对于eor1中,必定至少有一位为“1”(因为a 与 b不同)。
那么。我们便可以通过任意提取出一位不为零的“位”(假设D3 = 1)。再对数组中所有数进行分类,D3位为“1”的分为一类,“0”为另一类。那么对于a b 来说,一定分别在这两类之中。那么这时我们对其中任意一类进行依次异或,便可求出其中一个数。

最后,再将该数与最开始的eor1异或,便可得到另外一个“奇数次”数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值