从LeetCode的一道题说起:
由于算法薄弱,刚开始想到的是列表的count方法,然而直接报出超出时间限制的错误,各路大神也都纷纷给出方法,哈希或者循环出两个集合相减等。但是我感觉最具典型算法思想的是数学计算法和异或,先来看下用数学方法怎么解:
然后另一种方法就是异或,先看下异或的一些知识。
异或是一种基于二进制的位运算,用符号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