Given an array of integers, every element appears three times except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Subscribe to see which companies asked this question
目的是统计在出现三个数的数组中查看出现一个数的数字,,,,普遍方法就是统计二进制中各个位数是否出现的是三的倍数,
我们只要统计出不是三的倍数的位置,然后转换成数字就行了;
class Solution {
public:
int singleNumber(vector<int>& nums) {
vector<int>temp(32,0);
// memset(temp,0,sizeof(temp));
for(int i=0;i<nums.size();i++)
{
for(int j=0;j<32;j++)
{
if((nums[i]>>j)&0x1)
{
temp[j]=temp[j]+1;
}
}
}
int result=0;
for(int i=0;i<temp.size();i++)
{
if(temp[i]%3!=0)
{
result+=(1<<i);
}
}
return result;
}
};
其他方法:
用两个数分别代表对应位1出现的次数对三取模为1、2。
<span style="font-size:18px;">class Solution {
public:
int singleNumber(int A[], int n) {
//总的来说,就是统计各个二进制位1出现的次数。
//可以用one,two的每个二进制位分别代表对应位1出现的次数对三取模为1、2。
//另外one,two的某个二进制位都为0时,则表示那位1出现的次数取模正好为0。
int one = 0, two = 0; //刚开始在每位上1都没出现,所以都是0。
int three = 0; //当one,two的某个二进制位都为1时,表明已经出现了三次,可以取模。
for (int i = 0; i < n; ++i)
{
two |= one&A[i];
one ^= A[i];
three = one&two;
//当出现三次后,one,two清0,相当于取模
one &= ~three;
two &= ~three;
}
return one|two; //因为不知道那个数是出现一次还是两次,所以将出现一次或两次的都返回
}
};</span>
这个算法是有改进的空间的,可以使用掩码变量:
ones
代表第i th 位只出现一次的掩码变量twos
代表第i th 位只出现两次次的掩码变量threes
代表第i th 位只出现三次的掩码变量
假设在数组的开头连续出现3次5,则变化如下:
ones = 101 twos = 0 threes = 0 -------------- ones = 0 twos = 101 threes = 0 -------------- ones = 0 twos = 0 threes = 101 --------------
当第 i th 位出现3次时,我们就 ones
和 twos
的第 i th 位设置为0. 最终的答案就是 ones。
int singleNumber(int A[], int n) { int ones = 0, twos = 0, threes = 0; for (int i = 0; i < n; i++) { twos |= ones & A[i]; ones ^= A[i];// 异或3次 和 异或 1次的结果是一样的 //对于ones 和 twos 把出现了3次的位置设置为0 (取反之后1的位置为0) threes = ones & twos; ones &= ~threes; twos &= ~threes; } return ones; }