异或相关操作(以题目为例——Python实现)


在相关编程语言(c,java,python等)中,我们经常会看到异或操作,异或和加减乘除都属于一个性质,但是运算速度比加减乘除等运算要快的多的多,当在算法中遇到对时间复杂度有要求的,可以尝试一下使用异或操作是否可以解决。

什么是异或操作

如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

异或也叫半加运算或者无进位相加,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位。

使用异或操作不用申请额外的空间

异或的性质

  1. 0^N = N
  2. N^N = 0
  3. 满足交换律和结合律,即a异或b = b异或a, (a异或b)异或c = a异或(b异或c)
  4. 同一批数异或所得的结果相同

使用异或实现交换操作

在这里插入图片描述
需要注意的是:两个数在内存里的地址一定不能一样
如果是在数组里实现交换操作,如下图
在这里插入图片描述
一定要保证 i 和 j 不能相等,其实在进行交换时最好还是使用新定义一个temp作为中间存储的方法来实现,上述的交换方法可以当做理解异或操作,不建议使用,因为你可能无法确保两个数在内存里的地址一样。

使用异或解决相关算法问题

1. 假设有一个arr数组,在这个数组中,有一个数出现了奇数次,其余都出现了偶数次,请你找出这个数。要求时间复杂度为O(N),空间复杂度为O(1)。

首先定义eor = 0;我们让eor遍历异或整个数组,遍历后,eor的值即为出现奇数次的那个数字。

eor = eor^a
eor = eor^b
eor = eor^c
……

具体实现代码如下:

eor = 0
arr = [1,3,1,2,1,1,5,3,2]
for i in range(len(arr)):
    eor ^= arr[i]

print(eor)

输出结果为
在这里插入图片描述

2. 假设有一个arr数组,在这个数组中,有两个数出现了奇数次,其余都出现了偶数次,请你找出这个数。要求时间复杂度为O(N),空间复杂度为O(1)。

由于这个可能有点绕,我就在纸上写出整个过程,尽量详细且清晰
在这里插入图片描述
代码实现如下:

#有两个数出现了奇数次,找出这两个数
med,med1 = 0,0
arr_1 = [1,3,1,2,1,5,3,2]
for i in range(len(arr_1)):
    med ^= arr_1[i]
# eor = a^b
# eor != 0
# eor的二进制位中必有一个位置为一,我们找出最右的位置
rightOne = med & (~med+1) #提出最右的1

for i in range(len(arr_1)):
    if((rightOne & arr_1[i])==rightOne): #写!=也可,目的就是将数组分为两部分
        med1 ^= arr_1[i]
        
print('出现奇数次的两个数为: {}和{}。'.format(med1,med1^med))

输出为:
在这里插入图片描述

关于rightOne = med & (~med+1)这句代码,它的目的就是找到二进制位表示中的最右边的1,举例如下
med : 1010111100
~med : 0101000011 取反码
~med+1 : 0101000100
med & ~med+1 : 0000000100

关于异或操作本人目前就理解这么多,如有错误请多多包涵,谢谢指导。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ap21ril

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值