Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory注:一组数每个数都出现两次除了其中某个数,请找出这个只出现一次的数,不适用额外空间。
关于计数问题常考虑hashmap,可以通过键值对应进行计数,然后遍历查找只出现一次的数据,时间复杂度和空间复杂度都是O(N),这里题目要求额外空间复杂度O(1),一种方法是遍历数组元素,全部数组元素进行异或运算,最后结果就是那个只出现一次的数据,我们可以自己写几组测试数据分析下,基本思想就是 A^B^C^B^C = A ,这里我们不使用这种方法,因为leetcode上还有一道题目是数组中元素除了某个元素只出现一次外,其他元素都出现三次,然后让我们寻找这个元素,这样的话,上述异或方法就不适用了。
我们的思路是将每个数看成二进制序列,int型32位即可表示(当然程序中要考虑正负数问题),我们这里主要讲述思想,明白了之后具体细节可以参考代码理解。我们对N个数的bit0~bit31分别进行求和运算,求和mod2运算(对于出现k次则就是求和mod k),也就是N个数的bit0叠加得到结果的bit0,N个数的bit1叠加得到结果的bit1,类似地我们得到结果的bit0….bit31,(高低位自行设定,保持一致)然后组成最终结果。
我们以bit0为例进行分析,N个数中假设除了目标数外每个数都出现K此,假设除了目标数外的N-1个数中有x个数bit0为0,N-1-x 个数bit0 为1,目标数的bit0 为 b,则求和结果为(N-1-x)K +b ,求余后得到b,也就是目标数的bit0,所以按照上述方法可以得到目标数的二进制序列。具体编码中要使用移位运算和与运算,时间复杂度O(n).
public int singleNumber(int[] A)
{
//r is the return value
int r=0;
int mask = 1;
for(int i=1;i<=32;i++)
{
int bit = 0;
for(int j=0;j<A.length;j++)
{
//remember the priority of the operators "+" is higher than"<<"
int tmpbit = (A[j]&mask)>>(i-1);
//cuz java doesn‘t has unsigned int, we should deal with the negative integer
if(A[j] <0)
{
tmpbit = tmpbit&1;
}
bit = (bit+tmpbit)%2;
}
mask = mask<<1;
if(bit == 1)
{
r = r|(bit<<(i-1));
}
}
return r;
}
原文地址:http://blog.csdn.net/java_student09/article/details/46136181