一、性质
性质1
1、相同为0
2、不同为1
0^1=1
1^0=1
0^0=0
1^1=0
a=10110
b=00111
a^b=10001
性质2
无进位相加
性质3
1、0^N=N 、 N^N=0
2、交换律、结合律
3、n个数相异或,与谁先异或谁后异或无关,结果都相同。
原因:使用无进位相加解释,异或结果只与1的个数有关(偶数个1=0,奇数个1=1),与顺序无关
二、a、b交换
前提条件:a、b的内存不同
如果a、b内存相同,相当于自己和自己异或=0
//a=甲 b=乙
a=a^b; //a=甲^乙 b=乙
b=a^b; //a=甲^乙 b=甲^乙^乙=甲^0=甲
a=a^b; //a=甲^乙^甲=0^乙=乙 b=甲
三、力扣136题 及拓展
题目:
(1)给定一个非空整数数组,除了某1个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
(2)给定一个非空整数数组,除了某2个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
要求:
(1)时间复杂度O(n)。
(2)不使用额外空间
解答:
(1)
//题目(1) 所有数像异或
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans = 0;
for(int num:nums){
ans^=num;
}
return ans;
}
};
(2)
1、不妨设:a、b、others
eor=所有数相异或=a^b^others=a^b
2、因为a≠b,所以eor=a^b≠0
eor至少有一位为1
假设a、b在第6位不相同
则可以将所有数分为2组:
第6位是1的other1 | 第6位是0的other2
a(第6位是1) | a(第6位是0)
eor'=a^other1=a
b=eor^eor'=a^b^a=0^b=b
public static void printOddTimesNum2(int[] arr)
{
int eor = 0;
for(int i = 0;i < arr.length;i++)
{
eor ^= arr[i];
}
//eor=a^b
//eor!=0
//eor必然有一个位置上是1
int rightOne = eor & (~eor + 1);
//提取最右的1(找右边第一个不同的数):a^b取反+1 与原a^b相与
int onlyOne = 0; //eor'
for(int cur:arr)
{
if((cur & rightOne )==1) //分组
{
onlyOne ^= cur;
}
}
System.out.println(onlyOne + " " + (eor ^ onyOne));
}