欢迎fork and star:Nowcoder-Repository-github
137. Single Number II
题目
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
解析
-
由于除去目标元素target之外,所有元素都出现3次,假设出现3次的元素有n个,这样的话假如我们统计所有元素的某一位(比如最后一位),其一共有3n+1个二进制位。因为对与同一个元素来说,其所有的二进制位一定是相同的,所以对这些元素的某一位来说一定是以3个1或3个0为单位出现的,即3n+1个二进制位中一定是3x个1和3y个0,其中x+y=n,再外加一个target对应的二进制位(1或0都有可能)。综上所述,我们可以统计所有数字每一位上1的个数,对3取模,如果为1就说明target对应位为1,否则为0。
-
下面问题就是如何统计每一位上1的个数,一个比较好的方法就是采用位运算来处理,
//single number ii
class Solution_137 {
public:
int singleNumber(int A[], int n) {
int ret = 0;
for (int i = 0; i < 32;i++)
{
int cnt = 0;
for (int j = 0; j < n;j++)
{
cnt += (A[j] >> i) & 1;
}
ret += ((cnt % 3) << i);
}
return ret;
}
int singleNumber(vector<int>& nums) {
//对每一位进行累加,对次数取模运算
/* 把所有整数按照32位二进制进行每一位上的与1运算 结果为3n或3n+1;为3n+1的那些位就是只出现一次的数的二进制中1所在的位
*/
int ret = 0;
for (int i = 0; i < 32; i++)
{
int cnt = 0;//计每一位的1的个数
for (int j = 0; j < nums.size();j++)
{
cnt += (nums[i] >> i) & 1; //0的不需要考虑
}
//把3n+1的那些位的1移回原位并累加起来 |= 也行
ret += (cnt % 3) << i;
}
return ret;
}
};