思路一:
对于除出现一次之外的所有的整数,其二进制表示中每一位1出现的次数是3的整数倍,将所有这些1清零,剩下的就是最终的数。 用ones记录到当前计算的变量为止,二进制1出现“1次”(mod 3 之后的 1)的数位。用twos记录到当前计算的变量为止,二进制1出现“2次”(mod 3 之后的 2)的数位,用threes记录到当前计算的变量为止,二进制1出现“3次”(mod 3 之后的 2)的数位。当ones和twos中的某一位同时为1时表示二进制1出现3次,此时需要清零。即用二进制模拟三进制计算。最终ones记录的是最终结果。定义了三个变量,使用了constant space,符合题目的要求:without extra space
例如:5 1 5 5 0101 0001 0101 0101 过程 循环第一次后: ones = 0101 twos = 0000 threes = 0000 循环第二次后: ones = 0100 twos = 0001 threes = 0000 循环第三次后: ones = 0001 twos = 0101 threes = 0001 清0后: ones = 0000 twos = 0100 threes = 0001 循环第四次后: ones = 0101 twos = 0100 threes = 0100 清0后 ones = 0001 twos = 0000 threes = 0100
<span style="font-family:Microsoft YaHei;font-size:14px;">int singleNumber(int A[], int n) {
int ones = 0, twos = 0, threes = 0;
int i;
for(i = 0; i < n; i++){
twos |= (ones & A[i]);//<strong><span style="color:#ff0000;">二进制1出现2次的数位</span></strong>
ones ^= A[i];//<strong><span style="color:#ff0000;">二进制1出现1次的数位</span></strong>
threes = ones & twos; //<strong><span style="color:#ff0000;">二进制1出现3次的数位</span></strong>
ones &= ~threes;<strong><span style="color:#ff0000;">//清0</span></strong>
twos &= ~threes;<strong><span style="color:#ff0000;">//清0</span></strong>
}
return ones;
}</span>
参考:http://www.cnblogs.com/daijinqiao/p/3352893.html
思路二: 解题思路大致上就说定义一个int长度大小(32位)的数组,存放对应原数组中每个数的每个位的1的个数,当是3的倍数时,变成0,那么剩下来的就是那个单独的数了。一开始又想着这种想法挺不错的喔。但是题目不是要求线性时间复杂度吗?两个for循环不就是n的平方啦。后面看一下某人的解释,O(32n)就是线性的,跟O(n)一样。对哦。唉,那么简单的东西都忘了,真的是,唉。。。但是另外一个地方,申请了个int大小的数组,跟题目中的那个“without using extra memory”会不会有矛盾呢?好像申请常量空间是可以的
例如:5 3 5 5 0101 0011 0101 0101 过程 循环第一次后:i = 0,j从0到n之后: count[0] = 4 res = 0001 循环第二次后:i = 1,j从0到n之后: count[1] = 1 res = 0011 循环第三次后:i = 2,j从0到n之后: count[2] = 3 res = 0011 ...........
int singleNumber(int A[], int n) {
int count[32] = {0};
int i,j;
int res = 0;
for(i = 0; i < 32; i++){
for(j = 0; j < n; j++){
if( (A[j] >> i) & 1){
count[i]++;
}
}
res |= (count[i] % 3) << i;
}
return res;
}
参考:http://blog.csdn.net/u013592466/article/details/38337255