题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
注:num1,num2分别为长度为1的数组。将num1[0],num2[0]设置为返回结果,分别存这两个只出现一次的数字
分析
该题需要用到异或的知识,下面说一下异或的基本知识
异或的性质
1、对于任意的a有:a^a=0,a^0=a
2、交换律:a^b = b^a
通俗解释:相同的数异或为0,并且0和任何数异或都会是它本身。
所以如:[2,2,6,7,8,6,8,7,3,5],异或后相同的会抵消,最后只剩3和5异或的结果110,这两个数字就是只出现一次的数字,我们如何将其从异或的二进制数中找出来呢。这就要知道一个判断方法。如下面这句话。
一个数二进制从低位到高位第一个为1的寻找方法:n^(n-1)&n,n表示全部异或的结果
注:上面这个有点难理解,我们可以拿例子解释一下,如上面这个例子,最后全部异或后剩下3和5,3–>011,5–>101,两个异或结果为110,110^(110-1)&110=011&110=010,也就是第二位。假设flag = n^(n-1)&n
理解上面之后,具体分析如下:

代码如下:
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int res = 0;
for (int i = 0; i < array.length; i++) {
res ^= array[i];
}
//从低位到高位第一个为1的地方
int flag = res ^ (res - 1) & res;
num1[0] = 0;
num2[0] = 0;
for (int i = 0; i < array.length; i++) {
//与flag进行&操作后,两个子数组进行全部异或
if ((array[i] & flag) != 0) {
num1[0] ^= array[i];
} else {
num2[0] ^= array[i];
}
}
}
}

本文介绍了一种使用异或运算找出数组中仅出现一次的两个数字的方法。通过将数组中的所有数字进行异或得到一个结果,然后找到该结果中最右边的1位来区分两个不同的数字,再次异或后得到最终结果。
&spm=1001.2101.3001.5002&articleId=111144000&d=1&t=3&u=92f52b724bb84d89bdb825c745a3e891)

被折叠的 条评论
为什么被折叠?



