剑指 Offer 56 - I. 数组中数字出现的次数

该代码实现了一个解决方案,通过异或操作在给定的整数向量中找出两个只出现一次的数。首先计算所有数的异或结果,然后找到一个不为零的二进制位作为分组依据,将数组中的数按此位进行分组,最后异或两组的数得到两个单数。
摘要由CSDN通过智能技术生成

题目要求时间复杂度是O(n),空间复杂度是O(1)。

异或可以将两个只出现一次的数筛选出来,之后再把这两个数分到两组中,并且将相同的数分到同一组,两组分别异或就能求出两个数。
异或规则是不相同为1,相同为0
所以利用a^b 的结果中为1的某一位作为判断依据

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        
        
        int res=0,a=0,b=0;
        for(int i:nums){
            res^=i;
        }
        int div=1;
        //判断依据
        while((div&res)==0){
            div=div<<1;
        }
        for(int i:nums){
        //因为a,b不同  所以和div与运算会有不同结果
            if(div&i){
                // cout<<"aaaa "<<i<<endl;
                a^=i;
            }
            else{
                // cout<<"bbbb "<<i<<endl;
                b^=i;
            }
        }

        return vector<int>{a,b};
    }
};

剑指 Offer 56 - II. 数组中数字出现的次数 II

将所有数的每一位出现的次数相加 最终结果为3的倍数或者3的倍数余1
所以我们找出3的倍数余1的所有位就是出现一次的数

因为有些数出现三次 所以我们把三次用三种状态表示出来 分别为 00 01 10
出现次数相加 最后状态为 00或01 ‘也就是说我们要找出01状态的所有位

我们用one和two来表示 初始化one和two为0 表示00状态
比如说 n=3

n0011
two0000
one0011

为什么最后返回one
因为最终状态为01 two这一位为0 所以只要返回one就行了

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int one=0,two=0;
        for(int i:nums){
            one=one^i&~two;
            two=two^i&~one;
        }
        return one;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值