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());
        }
    }

  

posted @ 2024-03-28 11:48  dmfsimle  阅读(11)  评论(0)    收藏  举报