4.异或及两道题
1.异或(相同为0,不同为1)的特点:
a.0和任意数异或得到任意数
b.数值N和他自己异或,得到0
c.异或符合交换律和结合律(交换律:a^b=b^a 结合律:a^b^c=a^(b^c))
d.任意一组数,无论什么异或顺序,结果都一样(可通过结合律推导)
两道有关异或的题:
1)有一组数,其中一个数出现奇数次,其他数出现偶数次,求这个数?
解:将所有数进行异或操作,最后得到的数,就是这个数;(原理,一个数和他自己异或得到0,0和任意数异或得到这个数)
代码:
public class XORTest {
//异或test
public static int getXorNum(int[] arr){
int temp=0;
for (int a:arr) {
temp^=a;
}
return temp;
}
public static void main(String[] args) {
int[] arr = new int[]{2,2,2,5,5,9,2,9,6};
System.out.println(getXorNum(arr));
}
}
2)有一组数,其中2个数出现奇数次,其他数出现偶数次,求这两个数?
解:假设这两个数是a和b
a.将所有的数进行异或操作,得到的数就是这两个数的异或结果,即a^b;
b.因为是2个数,所以这两个数不同,那么如果将这两个数分成2组,那么其中一位一定是不同的;
比如说,第八位不同,那么a和b肯定属于2个不同的组;
通过只异或一个组的数,就能得到其中一个数,a或者b,假设是a;
c.通过第一步得到的数a^b,再异或第二步得到的数,就可以得到另外一个数;a^b^a=b;
代码如下:
public class XORTest2 {
//异或练习
//问题:有一组数,其中有二个数出现奇数次,其他数出现偶数次,求这两个数?
public static void getXorNum(int[] arr){
//1.所有数进行异或,得到a^b
int xor1=0;
for (int a:arr) {
xor1^=a;
}
//2.将数分组,得到其中一个数
int temp=xor1&(~xor1+1);//找到那个1
int Xor2=0;
for (int a:arr) {
if((a&temp) == 0)Xor2^=a;
}
System.out.println(Xor2);
System.out.println(Xor2^xor1);
}
public static void main(String[] args) {
int[] arr=new int[]{2,2,2,5,5,9,2,9,6,7};
getXorNum(arr);
}
}
其他方法:
public static void getXorNum2(int[]arr){
Map<Integer ,Integer> mymap=new HashMap<>();
for (Integer a:arr) {
if(mymap.containsKey(a)){
mymap.put(a,mymap.get(a)+1);
}else
mymap.put(a,1);
}
for (Map.Entry<Integer,Integer> b: mymap.entrySet()) {
// System.out.println(b.getKey()+"-"+b.getValue());
if(b.getValue()%2 != 0) System.out.println(b.getKey());
}
}

浙公网安备 33010602011771号