两个相同的数字异或结果会抵消,0与任何数异或都等于该数本身。

如何将两个数异或的结果拆分成原来的两个数:找出两数某一个不同位,然后将原序列与其位相与,分出不同的两组

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型vector 
     * @return int整型vector
     */
    vector<int> FindNumsAppearOnce(vector<int>& array) {
      int tmp = 0;
      int bit = 1;
      std::vector<int> res(2, 0);
      
      //  重点在于将两个数分开
      
      //  这里得到两个只出现一次的数异或出来的结果
      //  因为两个数不相同必定有一位是异或结果为1的
      for (int i = 0; i < array.size(); ++i) {
        tmp ^= array[i];
      }
      
      //  找出tmp即异或结果为1的那一位,就是两个数对应位取值不同的那一位
      while ((bit & tmp) == 0) {
        bit <<= 1;
      }
      
      //  因为两个数相应位不一样,而筛选是通过该位筛选,故两个数被分到不同的组别
      for (int i = 0; i < array.size(); ++i) {
        if ((bit & array[i]) == 0) {
          //  至于出现两次的数字,必定被分到同一组。所以抵消后就各自剩下出现一次的数字
          res[0] ^= array[i];
        } else {
          res[1] ^= array[i];
        }
      }
      
      if (res[0] < res[1]) {
        return res;
      } else {
        return {res[1], res[0]};
      }
    }
};