LeetCode第 137 题:只出现一次的数字II(C++)

137. 只出现一次的数字 II - 力扣(LeetCode)
在这里插入图片描述

这题的进阶:LeetCode第 136 题:只出现一次的数字(C++)_zj-CSDN博客

哈希表

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_map<int, int> m;
        for(int i = 0; i < nums.size(); ++i)
            ++m[nums[i]];
        for(auto c : nums){
            if(m[c] == 1) return c;
        }
        return 0;
    }
};

倍数计算

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_set<int> s;
        long sum = 0;
        for(int i = 0; i < nums.size(); ++i){
            sum += nums[i];
            s.insert(nums[i]);
        }    
        long val = accumulate(s.begin(), s.end(), long(0));
        return (3*val - sum)/2;
    }
};

位运算

考虑数字的二进制形式,对于出现三次的数字,各二进制位出现的次数都是 3 的倍数。所以,把所有数字展开为二进制形式,统计所以数字的二进制中1出现的次数,然后对3取模,剩下的就是只出现一次的数字,如图(来自:137. 只出现一次的数字 II(有限状态自动机 + 位运算,清晰图解)):

在这里插入图片描述

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res = 0;
        for(int i = 0; i < 32; ++i){
            int cnt = 0 ;
            for(auto num : nums){
                cnt += (num >> i) & 1;
            }
            res ^= (cnt%3)<<i;//<<的优先级高于 ^=
        }
        return res;
    }
};

对比上图:

i = 0时,最右边累计1的个数,cnt = 4, 4 % 3 = 1,1就是目标数(只出现一位的那个数)的最右边的位(右起第一位)。

i = 0时,右起第二位累计1的个数,cnt = 3, 3 % 3 = 0,0就是目标数(只出现一位的那个数)的右起第二位。

。。。

依次计算即可。

这种方法可以推广到某个数出现一次,其他数出现k次的情况,如果k为偶数,直接异或运算就行,如果k为奇数,将本方法中的对3取模改为对k取模即可。

逻辑位运算

当年数字逻辑电路的知识了,都忘了。可以看这个题解:

逻辑电路角度详细分析该题思路,可推广至通解 - 只出现一次的数字 II - 力扣(LeetCode)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值