面试题40 数组中只出现一次的数字

题目一:一个数组里除了一个数之外,其他的数都出现了两次,请找出这个数。


思想:题目里强调, 一个数字出现了一次,其余的都出现了两次。我们想到异或的一个性质:任何一个数字异或自身等于0.也就是说,如果我们从头到尾异或数组中的每一个数字,那么结果为只出现一次的数字,因为出现两次的数字全部抵消了。


void FindNumberAppearOnce(int  data[] ,int length ,int  *num)

{

int i;

*num=0;

for(i=0;i<length;i++)

*num^=data[i];

}


题目二:如果数组里有两个数字只出现了一次呢?


思想:根据上面的思想,我们试着把原数组分成两个数组,使得每个数组符合题目一的性质,如果能这样拆分,我们就可以按照题目一的方法找到这两个数。

我们还是从头到尾异或数组中的每一个数字,最终得到的是两个只出现一次的数字的异或结果。因为他们不同,所以异或结果一定不等于0,我们在结果里找到第一个为1的位的位置,根据这个位是否为1我们将数组分为两组。 这两个数组都符合题目一的性质。

void FindNumberAppearOnce(int data[],int length ,int *num1,int *num2)

{

if(data == UNLL || length <2)

return ;

int resultOfOR=0;

for(int i=0;i<length;i++)

resultOfOr ^=data[i];

int  indexOf1=FindFirstBitIs1(resultOfOr);


*num1=*num2=0;

for(int j=0;j<length ++j)

{

if(IsBit1(data[j],indexOf1))

*num1^=data[j];

else

*num2^=data[j];

}

}


unsigned int FindFirstBitIs1(int num)

{

int indexBit = 0;

while( (indexBit<8*sizeof(int)) && (num&1==0))

{

num>>1;

++indexBit;

}

return indexBit;

}


bool IsBit1(int num, unsigned int  indexBit)

{

num = num>>indexBit;

return(num&1);

}


题目三:如果三个数只出现了一次呢?

思想:

比如,1,2,3,1,2,3,4,5,6。在这个数组中,456出现了一次,123出现了两次。那么我们的目的就是求出456。

首先我们可以想到的是,这个数组绝对是有奇数个元素的。

那么我们可以根据不同的bit的值【不是1就是0】,将数组分成两个数组。第一个数组该bit为1,记该数组的元素个数为count1,第二个该bit为0,记该数组的元素个数为count0。

那么,先判断count1和count0哪个是奇数。

针对奇数的那个数组,比如说是count1,另外一个数组的的所有数字异或,结果可能为0【说明所有的三个只出现一次的数字都在count1的那个数组中】,也可能不为0【说明三个只出现一次的数字有两个在本数组中】。

如果第二个数组的异或结果不为0,那么第一个数组的所有值异或起来就是一个答案,记为a,再在第二个数组中找到那两个数字就可以了。

如果第二个数组的异或结果为0,那么三个数字都在第一个数组中。继续根据其他bit来划分。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值