一看到什么,某些数字出现了多少次,某些只出现了多少次都可以考虑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}; }
```