异或运算详解
异或(XOR)是一种基本的位运算,用于按位比较两个数。其符号为 ^
,在许多编程语言(如 Java、C++、Python 等)中使用。
1. 什么是异或?
异或运算是对两个二进制位进行比较:
- 如果两位相同,结果为
0
。 - 如果两位不同,结果为
1
。
输入 A | 输入 B | A ^ B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
例子:
对于两个整数 a=5a = 5a=5 和 b=3b = 3b=3,二进制表示如下:
- a=5a = 5a=5 →
0101
- b=3b = 3b=3 →
0011
a⊕b=0101⊕0011=0110a \oplus b = 0101 \oplus 0011 = 0110a⊕b=0101⊕0011=0110,结果是 666。
2. 异或的性质
2.1 交换律
A⊕B=B⊕A A \oplus B = B \oplus A A⊕B=B⊕A
示例:
System.out.println(5 ^ 3); // 输出 6
System.out.println(3 ^ 5); // 输出 6
2.2 结合律
(A⊕B)⊕C=A⊕(B⊕C) (A \oplus B) \oplus C = A \oplus (B \oplus C) (A⊕B)⊕C=A⊕(B⊕C)
示例:
System.out.println((5 ^ 3) ^ 2); // 输出 4
System.out.println(5 ^ (3 ^ 2)); // 输出 4
2.3 恒等律
A⊕0=A A \oplus 0 = A A⊕0=A
示例:
System.out.println(5 ^ 0); // 输出 5
2.4 自反性
A⊕A=0 A \oplus A = 0 A⊕A=0
示例:
System.out.println(5 ^ 5); // 输出 0
2.5 可逆性
(A⊕B)⊕B=A (A \oplus B) \oplus B = A (A⊕B)⊕B=A
- 异或的可逆性是其最重要的性质,常用于交换值或加密操作。
示例:
int a = 5, b = 3;
a = a ^ b; // a = 6
b = a ^ b; // b = 5
a = a ^ b; // a = 3
System.out.println("a = " + a + ", b = " + b); // 输出 a = 3, b = 5
3. 异或的常见用途
3.1 用于交换两个变量的值
异或可以在不使用临时变量的情况下交换两个数。
int a = 5, b = 3;
a = a ^ b; // a = 6
b = a ^ b; // b = 5
a = a ^ b; // a = 3
System.out.println("a = " + a + ", b = " + b); // 输出 a = 3, b = 5
3.2 检查两个数是否相等
两个数相等时,异或结果为 0
。
int a = 5, b = 5;
if ((a ^ b) == 0) {
System.out.println("a 和 b 相等");
} else {
System.out.println("a 和 b 不相等");
}
3.3 寻找数组中唯一的数字
如果一个数组中,只有一个数出现一次,其他数均出现两次,可以用异或快速找到该唯一数。
思路:
- 对所有数进行异或运算,相同的数会抵消,最终结果是唯一的数。
示例代码:
public class FindUnique {
public static int findUnique(int[] nums) {
int result = 0;
for (int num : nums) {
result ^= num;
}
return result;
}
public static void main(String[] args) {
int[] nums = {2, 3, 5, 3, 2};
System.out.println(findUnique(nums)); // 输出 5
}
}
3.4 寻找数组中缺失的数字
给定一个长度为 n
的数组,其中包含从 0
到 n
的所有数字,但缺少一个数字。异或可以高效找到缺失的数字。
思路:
- 将数组所有数与
0
到n
的数进行异或,最终剩下的结果就是缺失的数字。
示例代码:
public class MissingNumber {
public static int findMissingNumber(int[] nums) {
int n = nums.length;
int result = 0;
// 异或数组中的所有数
for (int num : nums) {
result ^= num;
}
// 异或从 0 到 n 的所有数
for (int i = 0; i <= n; i++) {
result ^= i;
}
return result;
}
public static void main(String[] args) {
int[] nums = {0, 1, 3, 4};
System.out.println(findMissingNumber(nums)); // 输出 2
}
}
3.5 判断两个整数符号是否相同
对于两个整数 x
和 y
:
- 如果它们符号相同,
x ^ y >= 0
; - 如果它们符号不同,
x ^ y < 0
。
示例:
public class CheckSign {
public static boolean hasSameSign(int x, int y) {
return (x ^ y) >= 0;
}
public static void main(String[] args) {
System.out.println(hasSameSign(5, 3)); // 输出 true(符号相同)
System.out.println(hasSameSign(-5, 3)); // 输出 false(符号不同)
}
}
4. 异或的时间复杂度
异或运算的时间复杂度为 O(1)O(1)O(1),因为它是一个按位操作,仅需常数时间。
5. 总结
异或运算是一种功能强大且高效的位操作,具有以下特点:
- 基本性质:交换律、结合律、自反性等。
- 应用场景:交换变量、查找唯一数、判断符号等。
- 优势:高效、简洁,特别适用于数组、整数处理相关问题。
理解和熟练运用异或操作,对于掌握算法优化、数论相关题目非常重要。