常见算法之求数组中出现奇偶数次的数(2)

题目一:求出一个数组中只有一个数出现了奇数次。

本题需要用到计算机的位运算的异或运算,即二进制位相同取0,不同取1。再结合异或的结合律、交换定律。

a != b;   

a^b !=0;  a^a=0

a^b^c = a^c^b;

(a^b)^c = a^(b^c)

相同数异或得到0,不同数异或不为0。出现了偶数次的数异或在一起最后得0,再异或剩下的出现奇数次的数,最后就只剩下一个数,就是出现奇数次的数。代码很简单如下:

    private static int getOddNumber(int[] data) {
        int res = 0;
        for (int i : data) {
            res^=i;
        }
        return res;
    }

题目二:求出一个数组中有两个数ab出现了奇数次。

  1.  同样把所有数异或起来,偶数次的数异或在一起就得到0,剩下的异或在一起就是 a ^ b。
  2. a != b => a^b != 0,那么a^b一定存在一个二进制位为1,a b在这个二进制位要么一个为0,要么一个为1。所以根据这个二进制位分为两类:一类为1,一类为0,ab在不同一侧。
  3. 将这个二进制位的数&当前数为1数异或起来,偶数次的数异或结果为0,最后得到的要么是a要么是b。
 private static void getOddNumbers(int[] data) {
        //eor != 0 ,一定存在一个二进制位为1
        int eor = 0;
        for (int d: data) {
            eor^=d;
        }
        //提取最右边1
        int rightOne = eor & (~eor + 1);
        int onlyOne = 0;
        for (int cur: data) {
            if ((rightOne & cur) == 1) {
                onlyOne^=cur;
            }
        }
        System.out.println(onlyOne + " " + (onlyOne ^ eor));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知始行末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值