137-只出现一次的数

题目

137. 只出现一次的数字 II - 力扣(LeetCode) (leetcode-cn.com)

思路

我们知道对于异或运算, 0 ⊗ a = a 0 \otimes a = a 0a=a并且 a ⊗ a = 0 a \otimes a = 0 aa=0, 如果存在某种运算 ⊕ \oplus ,使得 0 ⊕ a = a 0 \oplus a = a 0a=a并且 a ⊕ a ⊕ a = 0 a \oplus a \oplus a = 0 aaa=0,那么我们只需要将所有数字使用该运算执行一次即可得到仅出现一次的数字。

我们知道异或运算能够实现 0 ⊗ a = a 0 \otimes a = a 0a=a并且 a ⊗ a = 0 a \otimes a = 0 aa=0是因为其按位实现了模2加,如果我们设计一个加法运算其按位实现模3加即可到达上述效果。

我们使用数组char bit[32]来保存一个特殊的32位整数,使其每个位可以是0、1或者2(普通的32位整数也可以表示成这种特殊的32位整数),我们可以通过按位实现模3加(即某个位的值到3时就将其置为0)来实现上述提到的运算 ⊕ \oplus

bit     num             bit
00       0         (00 + 0) % 3
00       1         (00 + 1) % 3
00   +   0     =   (00 + 0) % 3
...     ...             ...
00       1         (00 + 1) % 3
00       0         (00 + 0) % 3

代码

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        char bit[32] = {0};

        for(unsigned int n : nums) {
            int p = 0;
            while(n != 0)  {
                // 按位加
                if (n & 0x1) {
                    bit[p]++;
                    // 每个位执行模3加
                    bit[p] %= 3;
                }
                p++;
                n >>= 1;
            }
        }
        int r = 0;
        // 将特殊32位整数转换为普通32位整数
        for(int i=0; i<32; i++) {
            int c = 0x1 << i;
            r += bit[i] * c;
        }
        return r;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值