异或,同0异1,无进位加法
100
^ 011
= 111
其他:
- 0^N=N
- N^N=0
满足交换律和结合律
经典交换两个数的顺序
a=甲 b=乙
a=a^b 即a=甲^乙
b=a^b 即b=甲^乙 ^乙=甲^(乙^乙)=甲
a=a^b 即a=甲^乙^甲=(甲^甲)^乙=乙
此时
a=乙 b=甲
注意:以上交换,a和b可以是同一个值,但不可以是同一位置,否则双双置为0
怎么说呢,举个栗子
a=甲 b=甲 这是两个不同的位置
a=a^b 即a=甲^甲
b=a^b 即b=甲^甲 ^甲=甲^(甲 ^甲 )=甲
a=a^b 即a=甲^甲 ^甲=(甲^甲)^甲 =甲
a=甲 a=甲 这是同一个位置
a=a^a 即a=甲^甲=0
a=a^a 即a=0^0=0
a=a^a 即a=0^0=0
可明白?
一个数组,其中元素有一个出现奇数次,其余都出现偶数次,找到那个出现奇数次的数
int eor=0;
fori遍历:eor^arr[i]
//相同的元素抵消为0,剩下的数就是那个出现为奇数次的数了
如何把int数的最右侧的1提取出来
a&(~a+1)即可
即a&(-a)
一个数组,里面有两个数出现奇数次,其余出现偶数次
int eor=0;
fori遍历:eor=eor^arr[i]
此时eor为两个出现奇数次的数的异或结果 即 eor=a^b
把eor最右侧的1提取出来
int eor2=eor&(-eor)
此时 eor2为1的位置在 a或b中这一位也为1,且只有一个为1,因为如果都为1,则异或后为0
fori遍历,if eor2^arr[i]!=0 则这个arr[i]为a或b其中一个
比如是a
则b=eor^a
一个数组,里面有一个数出现M次,其余数出现N次,其中N>M
public static void mn(int[]arr){
//用一个32位的数组累计每个arr[i]的bit位
int[]bit=new int[32];
for(int i:arr){
for(int j=0;j<32;j++){
if((i>>j)&1!=0){
bit[j]++;
}
}
}
int res=0;
写法1 (我的)
for(int i=0;i<32;i++){
bit[i]%=N;
if(bit[i]!=0){
bit[i]/=M;
res+=Math.power(1,j)
}
写法2 (老师的)
for(int i=0;i<32;i++){
res|=1<<i
}
sout res;
}
}