面试题56(1):数组中数字出现的次数

题目

数组中只出现一次的两个数字
一个整型数组里除两个数字之外,其他数字都出现两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)
例如:输入数组{2,4,3,6,3,2,5,5},因为只有4和6这两个数字只出现了一次,其他数字都出现了两次,所以输出4和6.

解题思路

采用异或运算的性质:任何一个数字异或它自己都等于0
如果我们从头到尾依次异或数组中的每个数字,那么最终的结果刚好是那个只出现一次的数字,因为成对出现两次的数字全部在异或中抵消了。

  1. 从头到尾依次异或数组中的每个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。
  2. 找出异或结果中第一个为1的位的位置,记为第n位
  3. 以第n位是不是1为标准把原数组分为两个子数组,第一个子数组中美格尔数字的第n位都是1,第二个子数组中每个数字的第n位都是0.

代码

class Solution{
  public:
    unsigned int FindFirstBitIs1(int num)
    {
        int indexBit = 0;
        while(((num & 1) == 0) && (indexBit < 8*sizeof(int)))
        {
            num = num >> 1;
            ++indexBit;
        }
        return indexBit;
    }

    bool IsBit1(int num,unsigned int indexBit)
    {
        num = num >> indexBit;
        return (num & 1);
    }
    
    void findNumsappearonce(int a[],int length,int *num1,int *num2)
    {
        if(a == NULL || length < 2)
        {
            return ;
        }
        int resultExclusiveOR = 0;
        for(int i = 0;i < length; ++i)
        {
            resultExclusiveOR ^= a[i];

        }
        //cout << "resultExclusiveOR: " << resultExclusiveOR << endl;
        int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
        //cout << "indexOf1: " << indexOf1 << endl;
        *num1 = *num2 = 0;
        for(int j = 0;j< length;++j)
        {
            if(IsBit1(a[j],indexOf1))
            {
                *num1 ^= a[j];
                //cout << "num1: " << *num1 << endl;
            }
            else
            {
                *num2 ^= a[j];
                //cout << "num2: " << *num2 << endl;
            }
        }
    }
};

完整代码见Github

你可能感兴趣的:(面试题56(1):数组中数字出现的次数)