异或,顾名思义,相同取0,相异取1,异或运算有结合律。在算法上有两个经典应用,一是交换两个数,二是寻找落单的数。
1.交换两个变量的值
与其它语言不同,C语言和C++语言的异或不用xor,而是用“^”,键入方式为Shift+6。(而其它语言的“^”一般表示乘方)
若需要交换两个变量的值,除了通常使用的借用中间变量进行交换外,还可以利用异或,仅使用两个变量进行交换,如:
1
2
3
|
a=a^b;
b=b^a;
a=a^b;
|
详解:
1
2
3
|
a1=a^b
b=a1^b
a=a1^b=a1^(a1^b)=a1^a1^b=b
|
注意:
1
|
a=a^b^(b=a);
//此类形式是不正确的UB行为,在不同编译器中会有不同的结果,切勿使用
|
这样就完成了a与b的交换。
综上:同一变量与另一变量和其异或值异或等于自身。
2. 落单得数(1个落单,2个落单):
要求时间复杂度O(n),空间复杂度O(1)。关于复杂度多说一句:
第一种思路是先快排,然后遍历寻找。时间复杂度是O(nlogn),空间复杂度是O(logn)。
O(n)这样的标志叫做渐近时间复杂度,是个近似值.各种渐近时间复杂度由小到大的顺序如下
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
第二种思路是采用哈希表,时间复杂度是O(n),空间复杂度也是O(n)。
第三种方法就是采用利用结合律的异或运算就可以了,这里面涉及到题目的延伸,如果两两成对的元素紧邻则直接异或,如果是散乱的则先快排再异或。