异或介绍
异或运算符 “^”, 它表示的实际意义为相同的为0, 不同的为1。即:即 0∧0=0,0∧1=1, 1^0=1,1∧1=0。
运算 | 说明 |
---|---|
0∧0=0,0∧1=1 | 0 ^ 任何数 = 任何数 |
1^0 = 1,1∧1=0 | 1 ^ 任何数 = 任何数取反 |
a ^ a = 0 | 任何数 ^ 任何数 = 0 |
异或实际应用
1、两数交换(不使用临时变量)
这道题有两种思路,第一种即是利用我们学过的加减法来对两数进行交换:
// 利用加减法对两数进行交换
int a = 5, b = 10;
a = a + b;
b = a - b;
a = a - b;
第二种思路即是利用异或来对两数进行交换
// 利用异或对两数进行交换
int a = 5, b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
//不懂得同学可以在草稿纸上进行二进制异或计算
2、只出现一次的数字(leetcode 136. 只出现一次的数字 https://leetcode-cn.com/problems/single-number/.)
给定一个非空数组,除了某个元素只出现一次以外,其余数字均出现两次,找出只出现一次的元素。
//本题解题思路为:0 ^ 任何数 = 任何数, 因此我们设number = 0
// x ^ x = 0 ---> 最后剩下的数字即为只出现一次的数字
public int singleNumber(int[] nums) {
int number = 0;
for(int i : nums){
number ^= i;
}
return number;
}
3、面试题56 - I. 数组中数字出现的次数((leetcode 面试题56 - I. 数组中数字出现的次数https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/.))
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
本题相较于上一题思路是大致相同的,不过我们需要多加一步判断,由于数组中有两个数字只出现了一次,因此我们异或一次肯定是不可以的,我们需要换个思路。
(1)通过异或求出只出现一次的两个数字
(2)通过某种分类方式将这个数字分开(比如:我们可以按照奇偶来对两个数进行分开,此处我们需要使用到&运算符),然后分别对分组进行异或运算。
public int[] singleNumbers(int[] nums) {
int num = 0;
for(int i : nums){
num ^= i;
}
int mask = 1;
//此处通过&运算求出可以将两数进行区分的数字
//由于其他的数字两两相同,因此此处区分对其他出现两次数字无影响
while((num & mask) == 0){
mask <<= 1;
}
int a = 0, b = 0;
for(int i : nums){
//分别对两种类别进行异或,可以分别求出两种类别中只出现一次的数字
if((i & mask) == 0){
a ^= i;
}else{
b ^= i;
}
}
return new int[]{a,b};
}
未完待续…