【leetcode 剑指offer No.56】 数组中数字出现的次数的解题思路和易错点

记录一下此题的操作思路,由于题目要求时间复杂度为O(n),空间复杂度为O(1),所以肯定是不能使用借助其他数据结构或者双指针遍历的方法了。这里使用的是位运算符。

主要是异或运算符,首先贴出异或运算符的几点重要性质。

1.如果我们对 0 和二进制位做 XOR 运算,得到的仍然是这个二进制位。

a⊕0=a

2.如果我们对相同的二进制位做 XOR 运算,返回的结果是 0。

a⊕a=0

3.XOR 满足交换律和结合律。

a⊕b⊕a=(a⊕a)⊕b=0⊕b=b

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int res = 0;
        int a = 0;
        int b = 0;
        for(int i =0;i<nums.size();i++)
            res ^= nums[i];
        int h =1;
        while((res&h)==0)
            h <<= 1;
        for(int i =0;i<nums.size();i++){
            if((h&nums[i])==0)
                a ^= nums[i];
            else
                b ^= nums[i];
        }
        vector<int> num;
        num.push_back(a);
        num.push_back(b);
        return num;
    }
};

先使用res变量来记录所有数异或的结果,从异或结果上按位来看的话,有1的地方就是这两个变量产生的1(因为两个一样的数异或结果为0,异或又符合交换律)。所以这两个1必然是由这两个不同的数产生的,之后我们找到第一位不是0的位,用h变量记录下来。之后以这一位作为标志进行分组,与这一类&为1的分为一组,与这一类&为0的分为另一组。

分组的理由:因为这两个数是必然在不同的组内,然后相同的数必然在同一个组内。这之后在对两个组分别异或,就得到这两个数了。

需要注意的点:在c++中 == 运算符的优先级 大于 & 运算符的优先级,所以要用括号将 & 的两端给括起来,否则会导致结果出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值