异或运算的应用

异或,就是无进位的加法,相同为零,相异为一。其计算机符号为“XOR”。

特点:

(1) 一个数和 0 做 异或 运算等于本身:a^0 = a

(2) 一个数和 其本身 做 异或 运算等于 0:a^a = 0

(3) 异或 运算满足交换律和结合律:a^b^a = (a^a)^b = 0^b = b


常用操作:

1. 使某些特定的位翻转

        对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。

        10100001^00000110 = 10100111

2. 实现两个值的交换,而不必使用临时变量。

        a = a ^ b

        b = a ^ b

        a = a ^ b

        执行这三行语句之后便可实现a,b的值互换。但有一点需注意,不可对自己进行异或运算,否则会导致抹掉数值。

一个小技巧: 提取二进制数值R最右侧1的位

        rightone = R & ( ~R + 1 )

        设定 R = 01010110

        则 ~R = 10101001

        ~R + 1 = 10101010

        R & ( ~R + 1 ) = (01010110) & (10101010) = 00000010 即 第2位是R最右侧值为1的位

应用:位运算+异或

有一个数组Arr ,里面的值都是整型类型,用时间复杂度为n,空间复杂度为1的算法实现:

1)已知只有一个数组出现了奇数次,其他所有的数字都出现了偶数次。请找到这个出现奇数次的数字。

        利用位运算异或的特点,任何数和自己异或的结果都为0、任何数和0异或的结果都是它自身。

        对数组Arr进行遍历,把所有元素进行异或,结合交换律计算,出现偶数次的数字进行异或的结果都是0,最终的结果就是0和出现奇数次的数字进行异或,结果是这个数字本身。

       def get_1_num(Array):

                result = 0

                for ele in Array:

                        result = result ^ ele

                print 'The num is: ', result

        

2)已知有两个数字出现了奇数次,其他所有的数字都出现了偶数次。请找到出现了奇数次的这两个数字。

        承接第一问的思路,对Arr的元素遍历进行异或,最终结果是出现了奇数次的这两个数字异或的 结果。那么接下来就是如何获取这两个数字的具体值了。

        假设这两个出现奇数次的数字分别为a,b,这两个数字做异或结果不为0,说明它们有一位上的值是不同的;另外出现了偶数次的数字在该位上的值要么和a相同,要么和b相同。

        下面我们就提取a^b的结果值最右侧的1的位rightone,以此来把Arr里的元素进行分类:以a和b为代表的该位上数字值为0 或 1的两类。

        上面讲到,提取二进制数值R最右侧1的值的计算方法:

        rightone = R & ( ~R + 1 ) ,这里R = a ^ b = result

        接下来,继续遍历Arr数组,将元素依次和rightone进行异或,并将符合与rightone异或值为0(该指定位与rightone相同) 或者值为1(该指定位与rightone不同)的元素再单独进行异或,得到最终结果,记为result_new。这一步的主要目的就是将上面分出的两类数据取其一再次进行异或,最终的结果就是只出现奇数次的那个数字的值。

        def get_2_num(Array):

                result = 0

                for ele in Array:

                        result = result ^ ele

                rightone = result & ( ~result + 1 )

                result_new = 0

                for ele_new in Array:

                        if (rightone ^ ele_new == 0): #或者rightone ^ ele_new == 1

                                result_new = result_new ^ ele_new

                print 'The one of nums is :{},and another one is : {}'.format(result_new,result^result_new)

                        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值