[Data Structure and Algorithm C++ Implementation] 1. Usage of XOR

The original video is Zuo Chengyun's B station teaching



XOR: 0 if they are the same, 1 if they are different. A better way to remember: add without carry

  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,
Please add a picture description
we can use eor & (~eor + 1)this rightmost binary that can extract this number (eor) 1 and subsequent values, ie 100
Please add a picture description

Guess you like

Origin blog.csdn.net/Motarookie/article/details/131335055