The original video is Zuo Chengyun's B station teaching
Article Directory
XOR:
10010
^ 01100
--------
11110
nature
- 0 ^ N = N,N ^ N = 0
- a ^ b = b ^ a (commutative)
- a ^ b ^ c = a ^ (b ^ c) (combination law) the same pile of numbers, no matter how the XOR calculation order changes, the XOR must have the same result
1 XOR swap value
Swaps the values of two variables (without introducing additional temporary space). Note that a and b can be different variables but not the same variable.
a = a ^ b //第一行:a = a ^ b; b = b
b = a ^ b //第二行:a = a ^ b; b = b ^ a ^ b = a (因为b ^ b = 0, 0 ^ a = a)
a = a ^ b //第三行:a = a ^ b ^ a = b b = a
2 Find the only number that appears an odd number of times in the array
Requires time complexity O(n) space complexity O(1)
void printOddTimesNum(const std::vector<int>& arr)
{
int eor = 0;
for (int cur : arr){
eor ^= cur;
}
cout << eor << endl;
}
// eor = 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ .... ^ odd ^ 24 ^ 24 ^.....
// 最后 eor 会等于那个出现奇数次的,出现偶数次的数都被自己消除掉了
3 Find the two numbers that appear an odd number of times in the array
The array has two numbers that appear odd times, and the other numbers are even
(requires time complexity O(n) space complexity O(1) )
- We still have an odd number of times to get eor (full name exclusive OR) first, but in the end eor will be equal to a ^ b, because even times become 0
- Because these two numbers are different , if you convert them to binary, at least one bit will be different (one 0, one 1). The XOR calculation result of eor on this bit must be 0 ^ 1 = 1. At least one: Ingenious, although there may be many bits that are 1, we only need to take out one of them. Here, for convenience, directly take the rightmost one on eor that is 1 (using eor & (~eor + 1 ) ) .
- Taking out the rightmost 1 of eor is used to divide the array elements into two groups (the number whose bit is 0, and the number whose bit is 1). Because eor = a ^ b, and the bit of eor is 1, so ab must be different in this bit, so ab must be located in the two numbers respectively (the main purpose is to separate them)
- Then the key operation comes: use the new eor' to XOR all the array elements whose bit is 1. This step is the same as question 1.2, the result must be a or b, we assume eor' = a . Finally, use eor' ^ eor to get another odd number, namely eor = eor' ^ eor = a ^ a ^ b = b .
#include <iostream>
#include <vector>
void printOddTimesNum2(const std::vector<int>& arr)
{
int eor = 0;
for (const int& cur : arr){
eor ^= cur;
}
// 目前 eor = a ^ b , eor != 0 且必然至少有一个位是1
int rightOne = eor & (~eor + 1);
int eor1 = 0;
for (const int& cur : arr){
if ((rightOne & cur) == rightOne){
// 与该位为1的组所有元素进行异或
eor1 ^= cur;
}
}
// eor1 得到的是a 或 b 不确定
cout << eor1 << ' ' << eor1 ^ eor << endl;
}
The function of eor & (~eor + 1) in the code is to get the last 1 of the target binary string and all the 0s after it.
Assuming eor is 1010111100,
we can useeor & (~eor + 1)
this rightmost binary that can extract this number (eor) 1 and subsequent values, ie 100