一看到什么,某些数字出现了多少次,某些只出现了多少次都可以考虑N进制的加法,2进制的加法也就是异或

  • 全部异或结果等于a^b,因为其他数都是出现了两次,异或是2进制的加法,所以两次异或后就是0

  • 根据最后一位是1还是0将数字划分成两批,a和b就被分开了,这两批分别全部异或起来就能得到a,b

      public int[] FindNumsAppearOnce (int[] array) {
          if(array==null||array.length<2) return new int[]{};
          //1.全部异或一遍,结果变成了那两个数a^b
          int N = array.length;
          int res = 0;
          for(int i = 0;i<N;i++){
              res^=array[i];
          }
          //2.抓出能够体现a,b不同的特点,由于res=a^b,比如假设是01000110
          //由于是异或运算,那么最后一个1的位置肯定是a、b有一个为1,一个为0
          //由这个点进行区分:
          //3.将最后一个1抓出来
          int lastOne = res&((~res)+1);//~res+1 = 10111010->res&(~res+1)
                                     //         01000110
                                     //         00000010->抓到最后一位1了
          int a = 0;
          for(int i = 0;i<N;i++){
              if((array[i]&lastOne)!=0){
                  //这就是包含了那一位为1的情况
                  a^=array[i];
              }
          }
          int b = res^a;
          return a<b?new int[]{a,b}:new int[]{b,a};
      }
    

```