异或运算的巧妙应用

异或运算的巧妙应用

从某个地方听到一个题目,题目如下:有一个数组,里面有两个元素只出现奇数次,剩下的所有元素只出现偶数次,那么请你找出这两个出现奇数次的数字。

用遍历的方法可以解决这道题,但是需要开辟额外的数组存储每个数字出现的次数,空间复杂度太高。

这里通过奇数次和偶数次联想到使用异或运算。异或运算是运算数字的二进制位形式。异或运算是无进位的二进制加法。

数字 数字 结果
1 0 1
0 1 1
1 1 0
0 0 0

我们可以设一个变量eor=0,用eor去异或数组里的每一个数字,得到结果是eor=a^b,a、b分别是出现奇数次的两个数字。然后设另一个变量dor=0,假设eor二进制中第8位是1,就让数组中所有第8位是1的数字和dor异或,然后得到数字就是a。原因如下:a和b异或的结果中,第8位是1,则a和b的第8位一个是0,另一个是1,其他的数字只出现偶数次,在异或时都被消除了(变成0),当dor和第8位是0的数字异或之后,得到的数字就只能是a。再用dor去和eor异或,得到的数字就是b。示例如下:

public class Main {
    public static void main(String[] args) {
        int[] a1 = {1, 3, 2, 1, 2, 1, 2, 1, 2, 5, 4, 4, 7, 7};
        int eor = 0, dor = 0;
        for (int i = 0; i < a1.length; i++) {
            eor ^= a1[i];
        }

        int flag=eor&(~eor+1);   //提取最右侧的1所在的位数
        for (int i = 0; i < a1.length; i++) {   //让某一位是1的数字和dor异或
            if (((a1[i] >> flag) & 1) == 1) {
                dor^=a1[i];
            }
        }
        int a = dor;
        int b = a ^ eor;
        System.out.println("a="+a+", "+"b="+b);
    }
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注