1.一个整型数组,有一个数字出现一次,其余数字出现两次,找出这个只出现一次的数字。
解题思路:异或运算性质(两个相同的数字异或得0,0与一个数字异或得数字本身,而且异或运算是满足交换律的)
数组元素按位异或,(交换律可以想象成相同的数字参与运算的时候是相邻的)所有出现两次的数字异或之后得0,最后剩余的是0与出现一次的数字异或,所以最后的结果就是出现一次的数字
2.一个整型数组,其他数字出现三次,只有一个数字出现一次,找出这个出现一次的数字。
结题思路:
思路一:考虑位运算,将各个数字的二进制按位相加,对3取模,最后为1的位组合起来就是只出现一次的数字。
public int singleNum(int[] array)
{
int temp = 0;
for(int i=0; i<32; i++) {
int bits = 0;
for(int j=0; j<array.length; j++)
bits += (array[j]>>i) & 0x1; //每次取一位
temp |= (bits%3)<<i;
}
return temp;
}
思路二:设置三个变量,分别记录出现一次的位数和出现两次及三次的位数,分别为one two three ,初值均为0,针对数组中的每一个数a[i],
出现一次(所有奇数次的数字):异或操作可以实现,one^=a[i](最后保留为1 的位是对应出现奇数次的位)
出现两次:看前面是否出现过,因此two |= (one & a[i]) 用 | 运算是保留每次算出的结果
出现三次:出现奇数次且至少出现两次,因此three = (one & two)
最后,one中出现三次的数字为one^=three
two中出现三次的数字为two^=three
所以,出现一次的数字为最后的one。
public int singleNumber(int[] A) {
int one = 0;
int two = 0;
int three = 0;
for(int i=0; i<A.length; i++) {
two |= (A[i] & one); //在one之前更新
one ^= A[i];
three = (one & two);
one ^= three;
two ^= three;
}
return one;
}