剑指 Offer -- 数组中只出现一次的数字(四十)

数组中只出现一次的数字(四十)

题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。

代码(已在牛客上 AC)

这道题的思路是, 先对整个数组求异或, 因为保证其他数字都出现偶数次, 而其中两个数字都只出现一次, 那么异或的结果 res 肯定不为 0, 这样的话, res 的二进制表示中肯定有为 1 的位(假设为第 k 位), 比如 res 的二进制如果为 10010, 那么第 1 位以及第 4 位为 1. 之后遍历整个数组, 将其中的元素根据其二进制表示中的第 k 位是否为 1, 将数组中的元素分为了两组 A 和 B, 其中 A 中除了某元素 num1 只出现了一次外其他元素都出现偶数次, B 亦同理.
那么分别对子数组 A 和 B 求异或即可得到 num1num2 的值.

那么现在的问题是如何判断某个数的二进制表示中的第 k 位是否为 1. 根据 res & (res - 1)res 存在如下关系: 前者是由后者的二进制表示去掉最右边的 1 形成的(比如 res10010, 那么 res & (res - 1) 结果为 10000), 这样的话, 两者的异或就是一个 mask(比如前面的例子, 两者异或的结果为 00010), 刚好可以用来判断第 k 位是否为 1.

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        if (data.size() < 2) return;
        int res = 0;
        for (auto &d : data) res ^= d; // 1. 首先求出所有元素的异或结果
        int mask = ((res & (res - 1)) ^ res);
        *num1 = *num2 = 0;
        for (auto &d : data) { // 3. 将元素按照 idxBit 这一位是否为 1 进行分组
            if (isBit1(d, mask)) *num1 ^= d; // 4. 将同一组的元素进行异或
            else *num2 ^= d;
        }
    }
private:    
    bool isBit1(int num, int mask) {
         return (num & mask);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值