前言:
异或运算一直是一种神奇的运算。它的运用很广泛,尤其是在密码学的加密技术中,但是同时在其他领域也很发挥着重要的作用。本文诣在介绍异或运算运算性质与一些常见的有趣习题。
有趣的思考
提供一个序列 , 它由 n - 1的数字组成。其中数字 , 属于 1 到 n 且每个数字只出现一次。要求空间不超过4MB , .
请你找出缺失的那个数字是哪个?
例如:
输入:
4
1 2 3 5
输出:
4
进入正片
XOR 是什么 ?
异或的英文表示: Exclusive OR ( Exclusive 独家的, 排斥的)
异或运算是一种作用于比特位的运算符 , 它由 ^ 表示。
真值表如下:
| x | y | x ^ y |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
它是作用于每一个比特位上的 , 所以只要任意一个对应的比特位上符合此运算, 那么所有的比特位都符合此运算。
很显然 , 通过观察此真值表 . 我们可以发现异或的运算的运算规则.
运算规则: 比特位相同即是 0 , 不同即是 1
举个非常简单的例子
x = 011 ----> 3
y = 101 ----> 5
x : 0 1 1
y : 1 0 1
x ^ y : 1 1 0 -----> 6
XOR 运算性质
性质1 : x ^ 0 = x
观察真值表:
| x | 0 | x ^ 0 |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 0 | 0 |
可以发现 , 其实 x ^ 0 = x , 其中称 0 是 x 的幺元.
性质2 : x ^ x = 0
通过真值表可以证明!
| x | x | x ^ x |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 1 | 0 |
例如:
x = 101 ----> 5
x = 101
x = 101
x ^ x = 0
性质3 : 交换律
交换律: ^ = ^
通过真值表可以证明:
| x | y | x ^ y | y ^ x |
|---|---|---|---|
| 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 0 | 0 | 0 | 0 |
结合 性质1 、 2 、 3 , 我们可以发现一个技巧!
假设我们这样有这样的一段序列 ^ ^ ^ ........ , 那么中间存在的重复出现数对 , 可以直接抵消且不会对结果有任何影响
性质4 :结合性
结合性: ^ ^ = ^ ^
意思是: 左边先结合、或者右边先结合其实都是可以的!
注意这里有一个小小的技巧:
^ =
^ =
介绍完性质 , 我们来介绍一些有趣的问题
2、 开始的问题
4MB的空间 , 改变不能通过开数组建映射(压缩成bit位存储也超出), 但是数据要求就是O(n) 必须跑完. 这时候就可以利用性质,将数据全部压缩存储在一个变量中。
形式化表达
^ ^ ^ ^ ^
因为序列元素的范围是数值范围是 1 到 n , 只有 n - 1 个数 , 且每个数出现一次. 所以我们可以考虑将这个 异或上 1 - n , n 个数. 这样出现的数就会重复的被计算两次 , 就会抵消.
那么之前出现的数都会被抵消掉 , 只留下那个缺失的数字!
形式化表达
^ ^ ...... ^ ^ ^ ...... ^
最后ans 就是答案!
2、交换两个数
假设我们需要交换的数 x , y
其实这个就比较简单了。 代码就是这样
int a , b;
std::cin >> a >> b;
// 交换两个数
a ^= b; // a ^ b
b ^= a; // a ^ b ^ b == a
a ^= b; // a ^ b ^ a == b
3、唯一的奇数
在一堆偶数出现出现次数的数中找到唯一出现次数为奇数的数
- 答案非常简单:这堆数异或和 , 原因请读者自己根据性质求证!
4、数集中缺失的两个数
描述:给定一个数集,数字的范围是1-n 且每个数字是只出现一次,请你找到缺失的两个数?
对于这个问题,设我们需要找到的数为 x , y 考虑将数集全部异或上 1 到 n , 那么我们可以得到 x ^ y 因为异或的运算规则,在bit位上相同为 0 , 不同为 1。 那么我们只需要找到,x ^ y bit第一个出现的位置 i。划分成两块 , 每块都存在两个集合。
- 第一块 i 号位置为 0 (此处就比特位讨论)
- 数字1 - n 第i号位置为 0 的数
- 给定的数集的所有的第i号位置为 0 的数
- 第二块 i 号位置为 1
- 数字 1 - n 第i号位置为 1 的数
- 给定的数集的所有的第i号位置为1的数 将第一块的集合1 、2 异或就是其中的一个数 , 将第二块的集合1、2异或就是另外的一个数 答案就这么求出来!