异或(XOR) 是一种基础的位运算,符号为 ^。它针对二进制位进行操作,具有独特的逻辑特性,在算法优化、数据处理、加密等场景中应用广泛。
异或的核心原理
异或是对两个操作数的每一位二进制位进行独立运算,运算规则为:相同为 0,不同为 1
(即:0 ^ 0 = 0,0 ^ 1 = 1,1 ^ 0 = 1,1 ^ 1 = 0)。
示例:
以整数 3(二进制 011)和 5(二进制 101)的异或运算为例:
011 (3)
^ 101 (5)
--------
110 (6)
结果为 6(二进制 110),每一位均遵循 “相同为 0,不同为 1” 的规则。
异或的关键性质
异或的实用价值源于其独特的数学性质,这些性质是解决问题的核心工具:
自反性:x ^ x = 0任何数与自身异或,结果为 0(二进制每一位都相同,均变为 0)。
恒等性:x ^ 0 = x任何数与 0 异或,结果为其自身(二进制每一位与 0 运算,保持原数不变)。
交换律:a ^ b = b ^ a异或运算的顺序不影响结果。
结合律:(a ^ b) ^ c = a ^ (b ^ c)异或运算的分组不影响结果。
还原律:a ^ b ^ b = a一个数连续异或同一个数两次,结果为原数(利用 b ^ b = 0 和 a ^ 0 = a 推导)。
实用价值
不使用临时变量交换两个变量的值
传统交换两个变量需要临时变量(如 int temp = a; a = b; b = temp;),而异或可通过性质 5 实现无临时变量交换:
a ^= b; // a = a ^ b(此时 a 存储两数异或结果)
b ^= a; // b = b ^ (a ^ b) = a(利用结合律和 b^b=0,还原出 a)
a ^= b; // a = (a ^ b) ^ a = b(利用 a^a=0,还原出 b)
明确规定a != b 的时候才行,如果a=b就都清零了。
查找数组中 “只出现一次的数字”
若数组中除一个元素外,其余元素均出现两次,可利用异或的 x ^ x = 0 和 x ^ 0 = x 性质快速找到唯一元素:所有元素异或的结果 = 唯一出现一次的元素(因为成对的元素异或后为 0,0 与唯一元素异或后为其本身)。
leetcode例题
class Solution {
public:
int singleNumber(vector
int n = nums.size();
int t = 0;
for(auto x:nums){ t^=x;}
return t;
}
};
翻转二进制中的特定位
若需翻转一个整数的某几位(0 变 1,1 变 0),可利用异或与 “掩码(mask)” 结合:
掩码中需翻转的位设为 1,其余位设为 0;原数与掩码异或后,目标位被翻转,其余位不变(因 x ^ 0 = x)。
示例:翻转 num 的第 k 位(从 0 开始计数):
#include
using namespace std;
int flipBit(int num, int k) {
return num ^ (1 << k); // 1 << k 生成第 k 位为 1 的掩码
}
int main() {
int num = 5; // 二进制 101
int flipped = flipBit(num, 1); // 翻转第 1 位(0 基)
cout << flipped << endl; // 二进制 111(7),第 1 位从 0 变为 1
return 0;
}
判断两个整数是否同号
整数的最高位(符号位):正数为 0,负数为 1。
若两数同号,符号位异或结果为 0(0^0=0 或 1^1=0);若两数异号,符号位异或结果为 1(0^1=1)。
利用这一特性可快速判断同号性:
(a ^ b) >= 0;
>=0就是同号,反之异号。
简单加密与解密
利用异或的 “还原律”(a ^ key ^ key = a),可实现轻量字符加密:
加密:密文 = 明文 ^ 密钥;解密:明文 = 密文 ^ 密钥。
#include
#include
using namespace std;
// 加密/解密函数(同一函数,因异或两次密钥还原)
string xorEncryptDecrypt(const string& data, char key) {
string result = data;
for (char& c : result) {
c ^= key; // 异或密钥
}
return result;
}
int main() {
string plaintext = "Hello, XOR!";
char key = 'k'; // 密钥(任意字符)
string ciphertext = xorEncryptDecrypt(plaintext, key);
cout << "加密后:" << ciphertext << endl; // 乱码
string decrypted = xorEncryptDecrypt(ciphertext, key);
cout << "解密后:" << decrypted << endl; // 输出 Hello, XOR!
return 0;
}
加密后:#GK3$9J
解密后:Hello, XOR!
计算汉明距离
汉明距离是指两个等长字符串(通常是二进制字符串或二进制数)中,对应位置上字符不同的数量。
int hammingDistance(int x, int y) {
int xorResult = x ^ y; // 不同的位为1
int distance = 0;
// 统计1的个数(汉明重量)
while (xorResult) {
xorResult &= xorResult - 1; // Brian Kernighan算法
distance++;
}
return distance;
}
点击学习Brian Kernighan算法
总结
异或运算高效简洁,并且有多种妙手