异或

从LeetCode的一道题说起:

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

由于算法薄弱,刚开始想到的是列表的count方法,然而直接报出超出时间限制的错误,各路大神也都纷纷给出方法,哈希或者循环出两个集合相减等。但是我感觉最具典型算法思想的是数学计算法和异或,先来看下用数学方法怎么解:

给定一个数组arr,用集合给数组去重:set(arr),然后对集合求和*2,减去数组arr的和:2(a+b+c)(a+a+b+b+c)=c

然后另一种方法就是异或,先看下异或的一些知识。

异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。它与布尔运算的区别在于,当运算符两侧均为1时,布尔运算的结果为1,异或运算的结果为0。所以异或是一种不进位加法,如1+1=0,,0+0=0,1+0=1。

性质:

1、交换律(a^b==b^a)

2、结合律(即(a^b)^c == a^(b^c))

3、对于任何数x,都有x^x=0,x^0=x

4、自反性 A XOR B XOR B = A xor  0 = A

用法:

 在C语言中,若需要交换两个变量的值,除了通常使用的借用中间变量进行交换外,还可以利用异或,仅使用两个变量进行交换:

A = A XOR B

B = B XOR A

A = A XOR B

好吧,我承认刚看到上面句子的时候一脸懵B,换个写法会好很多:

a = A XOR B

B = B XOR a = B XOR A XOR B = A

A = a XOR B = A XOR B XOR A = B

这样写更容易理解。

十进制的异或

现实中用的都是十进制的数值,那么我们来看一看两个十进制数值是怎么进行异或计算:

5 ^ 3 = ?

进行异或前需要把两个数转换为二进制:0101   0011

  0101
XOR 0011
------  
结果 0110

 

 

 

将0110转换为二进制:6

既有5 ^ 3 = 6

解题:

如上,对异或有了简单了解后,上面的题目也可用异或解决:

def singleNumber(arr):
    a = 0
    for i in arr:
        a = a^i
    return a

 

 

posted @ 2019-11-04 10:19  一男、  阅读(514)  评论(0编辑  收藏  举报