异或运算练习(四)—— 找到数组中出现奇数次的2个数

数组中有2个不相等的数出现了奇数次,其余数出现了偶数次,如何找到这两个数。
之前练习中有过类似的题,不过是找到数组中1个出现奇数次的数,那两个数该如何找?

分析
假设两个出现奇数次数为a和b。

  1. 遍历数组,申请一个变量eor与数组中所有数都进行异或运算,因为相同数异或的结果为0,所以第一次异或的结果就是a ^ b,假设结果为c。
  2. 根据上一步得到的结果c,找到c的二进制中最右侧的1。可参考我上一篇博客看如何找到二进制中最右侧的1
  3. 找到c中最右侧的1(其他位置的1也可以)的位置index。说明a和b在index处是不同的(异或运算相当于无进位相加,如果此处数相同,则相加后为0)。
  4. 根据index可将整个数组分为两类,第一类是二进制中index处为1的数,第二类是二进制中index处为0的数。那么a和b因为不相等,并且index处不同,所以一定会在不同的分组中。
  5. 再次遍历数组,将数组中的每个值 & index(&:两个都是一则为一)。如果不为0,说明该元素二进制中index处不为0。又因为a、b已经明确的分为两类,所以此时可以得到其中一个的值,另一个用eor再次进行 ^ 运算,就可得到。

代码实现:

public static void findNum(int[] arr) {
        int eor = 0;

        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        //~eor + 1 -> -eor
        //找到eor中最右侧的1
        int rightOne = eor & (~eor + 1);
        int onlyOne = 0;
        for (int i = 0; i < arr.length; i++) {
        
            if ((arr[i] & rightOne) != 0) {
                onlyOne ^= arr[i];
            }
        }
        int otherOne = eor ^ onlyOne;
        System.out.println(onlyOne + " " + onlyOne);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值