【剑指offer】数组中只出现一次的数字

来源:互联网 发布:java saas多租户 架构 编辑:程序博客网 时间:2024/05/14 19:03

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

分析:我们都做过一个数组中除一个数字外,其他都出现2次的题目,很简单,我们只需要所有的元素相异或就可以了。但现在是2个数,异或的结果是2个数的异或结果,而其他的元素都出现2次,异或后为0。如果要是只有一个单独的数的话我们就会做,那么我们能不能把2个数的情况转化为1个数的情况呢?答案是肯定的。所有元素相异或后的结果是只出现一次的2个数异或的结果,由于是2个不同的数,肯定有某些位的异或结果为1,我们可以找到结果中最右边的1在第i位上,我们可以根据所有元素在第i位上的不同来分为2类,成对的元素一定是成对出现在其中一类中,只出现一次的元素必定分到不同的类中,最后分别把2类中的元素相异或就得到最终的结果。我判断第i位的值是先把数向右移动i-1位或除以2i-I然后在对2求模。

程序:

void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {        if (data.size() < 2) return;        int i = 1,sum=data[0];        while (i < data.size())  //sum保存2个数的异或结果;            sum =sum^data[i++];        if (sum == 0) return;        i = 0;        while (sum % 2 != 1){  //找到sum二进制从右到左的第一个1的位置(为1说明2个二进制数在此位上一定是不同的);      sum=sum>>1;    //或者t /= 2;       i++;        }int j=0;        vector<int> temp1, temp2;            while (j < data.size()){   //把data分为2类;            int k = i,tmp=data[j];    while (k!=0&&k--)        tmp=tmp>>1;  //或者tmp =tmp/2;              if (tmp % 2 == 1)  temp1.push_back(data[j]);            else temp2.push_back(data[j]);            j++;        }        i = 1; j = 1;        while (i < temp1.size())              temp1[0] = temp1[0] ^ temp1[i++];        while (j< temp2.size())            temp2[0] = temp2[0] ^ temp2[j++];        *num1 = temp1[0];        *num2 = temp2[0];    }

原创粉丝点击