数组中只出现一次的数字

思路:

如果只有一个数字,那么就好求了,直接异或,结果就是这个数字。

试着把原数组分成两个子数组,每个数组包含一个只出现一次的数字,其他数字都是成对出现。

怎么拆分呢?

1、先把数组从头到尾异或,最终得到的结果是这两个数字异或的结果,由于这两个数字不一样,所以异或的结果肯定非0,即结果数字的二进制表示中至少有一位是1。

2、记录从左往右数第0~n位的数是1,这个位置记录为n;

3、分组的标准就是这位是1就分在一组,是0就分在另一组。由于相同的两个数字这位上的数字肯定是相同的,所以这样的分发就是正确的;

4、最后两个分组分别从头到尾异或,得到的两个结果就是这两个数字了。

 1 class Solution {
 2 public:
 3     void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
 4         if(data.size()<2) return;
 5         int result=0;
 6         for(int i=0;i<data.size();i++) result ^= data[i];
 7         int index=find1(result);
 8         *num1 = *num2 = 0;
 9         for(int i=0;i<data.size();i++){
10             if(is1(data[i],index)) *num1^=data[i];
11             else *num2 ^= data[i];
12         }
13     }
14     //寻来寻找二进制从左到右第一个是1的位
15     int find1(int num){
16         int index=0;
17         while((num&1)==0 && (index<31)){
18             num = num>>1;
19             index++;
20         }
21         return index;
22     }
23     //根据这一位是不是1来分成两组
24     bool is1(int num,int index){
25         num = num>>index;
26         return num&1;
27     }
28 };

 

posted @ 2019-07-17 19:56  Austin_anheqiao  阅读(155)  评论(0编辑  收藏  举报