哇说这真的这个题还是有点难度的!!!
我们把大体的解题方式分为3步
第一步就是找出他们的“特殊值”
先补充一下就是对于^异或操作符是具有交换行和结合性的。
所以无论是什么数,或者再不同的地方只要异或在一起就会变成0。
比如4545。将·这几个数异或起来的出来的结果就是零。
根据这个特性我们将所有的数异或起来^便可以得到特殊值
“特殊值”
因为其他的数字都是2的倍数所以异或起来都是0,但是特殊值是这个数组中唯一2个不同的值异或起来的所以叫它为特殊值
第二步找出“特殊值”中最左边的1
这一步很简单我就直接贴代码了
eor & (~eor + 1)
其实我们可想而知就是当两个不同的数字进行异或的时候同位不同值数的数字异或出来就会是1。
同位同值异或出来就是0。
第三步将最左边的1和全部的数字进行异或找出是同位是0的值
因为根据异或的特性就可以看出特殊值是1的数字,原来两个数,同位绝对不是一样的。
所以就将两个不同的数分开了。
其实就是做这么一件事
看起来很难其实也很简单就是用循环进行全部异或然后再用选择进行分割。但是我们不要忘记一点就是当同样的数进行异或是0。所以当是0的部分再相互异或就会得出两个数其中的一个数
这个时候也不要忘记我们的特殊值 它是两个只出现一次数的异或值。
我们已经得出了其中一个数让它和特殊值进行异或就剩下了另一个。
好了贴代码
void find(int arr[], int siz) {
int eor=0;
for (int j = 0; j < siz; j++) {
eor ^= arr[j];
}
int last = eor & (~eor + 1);
int dsg=0;
for (int j = 0; j < siz; j++) {
if ((last & arr[j]) != 0) {
dsg ^= arr[j];
}
}
printf("%d %d",dsg, dsg ^ eor);
}
int main() {
int arr[] = { 1,1,2,2,3,3,4,7,5,5,6,6};
find(arr,sizeof(arr)/sizeof(arr[0]));
}