这个题目的思想是,书上说,由于题目中说了是其它的数字有两个,而这两个数字
只有一个,于是知:异或(不知道你有没有想到)。
解题的思路是:
先对数组中所有数字进行一次异或
int bitXORResult=0;
for(int i=0;i<Length; i++){
bitXORResult^=arr[i];
}
那么知道其实这个bitXORResult最后的结果就是那两个只出现一次的数字的异或的结果。也就4^6=2啰。
2也就是0X10嘛。
然后。我们将这个数组分成两个数组:怎么分?
根据这些数字的二进制表示的倒数第2位是不是1来分(因为bitXORResult=0x10).于是知,
int lastBitOne=findLastBitsOne(bitXORResult); //找到了从最后一位开始找为1的位
int findLastBitsOne(int v_bitsResult){
int shiftCount=0;
int bit=1;
while(v_bitsResult^bit==1){
shiftCount++;
v_bitsResult=v_bitsResult>>1;
}
return shiftCount;
}
找到bitXORResult中从最后开始最近一位是1的下标。
然后就根这个标志分成两组。那么这两个只出现一次的数组肯定出现在不同的数组中。我们知道由于其它的数字都是
成对出现的。那么对应的位要么是1,要么是0.那么其它的数字肯定成对出现在这些数组中啊,就像如下:
分成的数组1:2、3、6、3、2
分成的数组2:4、5、5
那有没有可能4、6(只出现一次)同时出现在同一个数组中呢? 不可能,为啥 ?
如果4、6同时出现在同一个数组中,也就是4、6对应的那位是相同啰。那么异或之后还是0罗。而其它数字对应的那个位是成对出现的(因为出现两次嘛)
于是它们的异或后结果也是0嘛。于是那么位不可能是1啊。与假设相矛盾。
那么只有可能是有一个只现一次的数中其对应的那个位是1(也就是数组中的6),另一个(4)对应的那位0罗。
ifndef ONE_TIME_ARR_H
#define ONE_TIME_ARR_H
#include<iostream>
int findLastBitsOne(int v_bitsResult);
bool isBitOne(int value,int bitIndex);
void findNumsApprenceOnce(int *arr,int Length,int *num1,int *num2){
if(arr==NULL||Length<=2){
return;
}
int bitXORResult=0;
for(int i=0;i<Length; i++){
bitXORResult^=arr[i];
}
if(0==bitXORResult){
return;
}
int lastBitOne=findLastBitsOne(bitXORResult); //找到了从最后一位开始找为1的位
*num1=0;
*num2=0;
for(int i=0;i<Length; i++){
if(isBitOne(arr[i],lastBitOne)){
(*num1)^=arr[i];
}else{
(*num2)^=arr[i];
}
}
}
int findLastBitsOne(int v_bitsResult){
int shiftCount=0;
int bit=1;
while(v_bitsResult^bit==1){
shiftCount++;
v_bitsResult=v_bitsResult>>1;
}
return shiftCount;
}
bool isBitOne(int value,int bitIndex){
value=value>>bitIndex;
return (value&1);
}
#endif